16

How can I check if a given type is a specialization of a particular class template? For instance, given

template <class T>
struct A {};

How can I check if CompareT is an A<*> for some type * in the following:

template<class CompareT>
void compare(){
   // is this A ?
   cout << is_same< A<*> , CompareT >::value;     // A<*> ????
}

int main(){
  compare< A<int> >();
}

For example, here A<int> should match A<*> and print 1.

Barry
  • 286,269
  • 29
  • 621
  • 977
tower120
  • 5,007
  • 6
  • 40
  • 88
  • [std::is_same](http://en.cppreference.com/w/cpp/types/is_same) ? – quantdev Aug 01 '15 at 14:35
  • @quantdev yes, but I need is_same that work for this case :) – tower120 Aug 01 '15 at 14:36
  • "is this A?" Is *what* A? What are you comparing to what? – Aaron McDaid Aug 01 '15 at 14:41
  • Maybe you mean: is the type `CompareT` an instance of the type template `A`? Is there some `X` (any `X`) for which `A` is `CompareT`? – Aaron McDaid Aug 01 '15 at 14:42
  • I meant A = A<*> (Same class, no matter what specialization) – tower120 Aug 01 '15 at 14:43
  • You keep writing `A<*>`. What does `*` mean? – Aaron McDaid Aug 01 '15 at 14:44
  • For example, you want `A` and `A` and `A` to be true. but `vector` and `vector` and `vector` to be false? – Aaron McDaid Aug 01 '15 at 14:48
  • A<*> is A < Any type here >. In other words I want to compare does CompareT (A) is specialized A – tower120 Aug 01 '15 at 14:49
  • @tower120 There are a few answers already, perhaps it would be productive to add comments there. – Potatoswatter Aug 01 '15 at 14:50
  • Aha. I think the word "specialized" threw me off. "template specialization" has a specific meaning that is different from the way you're using it. Maybe you should say "instance" or something like that. – Aaron McDaid Aug 01 '15 at 14:51
  • @AaronMcDaid it is, in fact, correct. A template specialization is the type that results from a template instantiation. An *explicit* template specialization is probably what you're thinking about. But I agree that this is all very confusing. – Quentin Aug 01 '15 at 14:55
  • @Quentin, I had thought that `vector` was "specialized" but that all other instances of `vector` were (non-special) instances. – Aaron McDaid Aug 01 '15 at 14:57
  • I never heard about template instantiation:) I thought that vector is specialization of vector . – tower120 Aug 01 '15 at 15:02
  • 2
    @AaronMcDaid (and tower120) *instantiating* a template means generating the final type (the *specialization*) by plugging in arguments for each template parameter. The implementation of the type is picked by pattern-matching its "signature", and the chosen one can be an *explicit* (like `std::vector`) or *implicit* (from the first and most general declaration) specialization. We further distinguish *partial* and *full* explicit specialization, depending on whether there are template parameters left. – Quentin Aug 01 '15 at 15:11

2 Answers2

25

Here's one where you can provide the template to be matched against :

template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};

template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};

static_assert(is_specialization<std::vector<int>, std::vector>{}, "");
static_assert(!is_specialization<std::vector<int>, std::list>{}, "");
Quentin
  • 62,093
  • 7
  • 131
  • 191
  • 4
    Note that this won't work for all templates, such as `std::array` which is mentioned in the question this was closed as a duplicate of. – Potatoswatter Aug 02 '15 at 01:51
  • 1
    @Potatoswatter indeed. Non-type template arguments are still annoyingly unflexible. – Quentin Aug 02 '15 at 13:48
  • Is there any workaround possible with "auto" template parameters in c++ 17? I am trying with no success, but I'm still not a master of c++ templates... – NicoBerrogorry Aug 29 '18 at 06:12
  • @NicoBerrogorry somewhat. `auto` can be used to deduce a non-type template parameter's type, so `std::array` can be matched by `template – Quentin Aug 29 '18 at 08:48
  • name `is_specialization` is misleading, since specialization means alternative implementation of template for specific type(s). IMO it would be better to use `is_instance_of` or `is_template_of`. – Marek R May 07 '21 at 16:12
  • 1
    @MarekR yes and no. Both are called [specializations](http://eel.is/c++draft/temp.spec.general#4.sentence-2), which can be explicit or implicit. I agree that not calling the result of a template instantiation an instance is a bit counter-intuitive, but I prefer to be consistent with the standard. – Quentin May 07 '21 at 18:11
10

CompareT is a type and A is a template. A class can't be a template, identically. A class can be a specialization of a template, so I'll assume that's what you want.

Partial specialization can do pattern-matching:

template<class T>
struct is_an_A // Default case, no pattern match
    : std::false_type {};

template<class T>
struct is_an_A< A< T > > // For types matching the pattern A<T>
    : std::true_type {};

template< class CompareT >
void compare() {
    std::cout << is_an_A< CompareT >::value;
}
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421