Way to deduce if type is from a templated class

class template argument deduction
c++ template class
c template type deduction
c++ template class constructor
c template return type deduction
template argument for template type parameter must be a type
c constructor with template argument
c++ template specialization

I've been trying to answer the question in the title, but I'm stumped. Basically, trying to see if there's a built-in way to tell the 'source' of a template instantiation, at least for classes. Here is an example of what I'd like to do:

template<class T>
class A { };

auto a = A<int>();

template<class T>
auto someFunction(T item) {
    if(/* if type of a is from the templated class A */) {
        // yep A<int> is 'from' A.
    }
}

Is this possible, in some way such as this? I could use some saved value or inheritance shenanigans to get something similar, but I'd rather not.

Maybe with a custom type traits.

Something as follows

template <typename>
struct is_A : public std::false_type
 { };

template <typename T>
struct is_A<A<T>> : public std::true_type
 { };

// ...

template <typename T>
auto someFunction(T item) {
   if( is_A<T>::value ) {
    // yep A<int> is 'from' A.
   }
}

Or, maybe, you want intercept non only A<T> but, generically, all types that are a template type, maybe with an undefined number of template arguments?

In this case you can try with something as follows

template <typename>
struct is_template : public std::false_type
 { };

template <template <typename...> class C, typename ... Ts>
struct is_template<C<Ts...>> : public std::true_type
 { };

Problem: this type traits intercepts all template types with types template arguments and only template arguments. But doesn't intercept, by example, std::integer_sequence<int, 0, 1, 2, 3, 4, 5> that receive a type and some non-type template parameter.

You can add other specializations for is_template, to intercept other cases, but you can't define a specialization that catch all template types (all combinations of template parameters).

Template argument deduction, Template type argument cannot be deduced from the type of class A { }; template<short s> void f(A<s>); // the type of the� Deduction for alias templates. When a function-style cast or declaration of a variable uses the name of an alias template A without an argument list as the type specifier, where A is defined as an alias of B<ArgList>, the scope of B is non-dependent, and B is either a class template or a similarly-defined alias template, deduction will proceed in the same way as for class templates, except

Use a type trait

#include <type_traits>
#include <iostream>

template<class T>
class A { };

auto a = A<int>();

template <typename X>
struct is_from_A : std::false_type {};

template <typename T>
struct is_from_A<A<T>> : std::true_type {};

int main() {
    std::cout << is_from_A<int>::value << "\n";     // 0
    std::cout << is_from_A<A<int>>::value << "\n";  // 1
}

13.10.2.5 Deducing template arguments from a type [temp.deduct.type], A type that is a specialization of a class template (e.g., A<int>) includes the types, is specified in a way that includes a non-deduced context, all of the types that� In the call to f, compilers use expr to deduce types for T and ParamType. When a variable is declared using auto, auto plays the role of T in the template, and the type specifier for the variable acts as ParamType. This is easier to show than to describe, so consider this example: auto x = 27;

An other way, allowing derived class to match:

template <typename T>
std::true_type is_an_A_impl(A<T>*);

std::false_type is_an_A_impl(...);

template <typename T>
using is_a_A = decltype(is_an_A_impl(std::declval<T*>()));

How to Use Class Template Argument Deduction, Class Template Argument Deduction (CTAD) is a C++17 Core const B& ) and the arguments of type int , A and B are deduced to be int , and� C++ templates can be used both for classes and for functions in C++. Templated functions are actually a bit easier to use than templated classes, as the compiler can often deduce the desired type from the function's argument list.

C++ Templates Tutorial, Create the required classes by plugging in the actual type for the type parameters . For example, currently the definition of template class vector Imagine how many changes would be required if there was no typedef! can be deduced from the actual template argument list. When defining a function as a member of a templated class, it is necessary to define it as a templated function: template<class a_type> void a_class<a_type>::a_function(){} When declaring an instance of a templated class, the syntax is as follows: a_class<int> an_example_class;

1. Deducing Types - Effective Modern C++ [Book], If you were happy with how C++98 deduced types for templates, you're set up to Of course, as a modern C++ developer, you'd naturally prefer a std::array to a� CTAD looks at a class template’s constructors, plus its deduction guides, in order to determine the type to construct. That deduction either succeeds (determining a unique type) or fails. Once the type to construct has been chosen, overload resolution to determine which constructor to call happens normally.

Template argument deduction for class templates (Rev. 6), If constructors could deduce their template arguments "like we expect from other Template arguments can only be left out this way from the "type" of the� Templates (C++) 12/27/2019; 7 minutes to read +2; In this article. Templates are the basis for generic programming in C++. As a strongly-typed language, C++ requires all variables to have a specific type, either explicitly declared by the programmer or deduced by the compiler.

Comments
  • just A<T>, or any C<Ts...> or also std::array<T, N> ?
  • Do you want to detect struct Der : A<int> {} ?
  • @Jarod42 just any A<T>s, but nothing else. So, excluding your next two examples.
  • Note that this violates LSP; make A final if you do this.
  • @Yakk-AdamNevraumont - ehmmm... sorry, I don't understand what do you mean.
  • Ah. en.wikipedia.org/wiki/Liskov_substitution_principle -- that a derived type can be substituted for its parent. If A<int> is non-final, and B derives from A<int>, your code will behave differently if passed A<int> than B. Hence violates LSP.
  • @max66 I believe this LSP substitution violation could be solved if the template used std::condition to determine if it inherited from true_type or false_type, instead of using specialization.
  • Lovely! Thank you. What is the name of the syntax in the line struct is_from_A<A<T>> : ...? I thought template specializations could only use explicit values, i.e. is_from_A<A<int>> : ..., but apparently this is not the case.
  • @AnthonyMonterrosa: And so it is partial specialization (not available for function BTW).