6

Is there any way of detecting whether a class is a normal type or is an instantiation of a template type (meta type) which may include non-type parameters? I came up with this solution:

#include <iostream>

template <template<class...> class> 
constexpr bool is_template()
{
    return true;
}

template <class> 
constexpr bool is_template()
{
    return false;
}

struct Foo{};

template<class> struct TemplateFoo{};

template<class, int> struct MixedFoo{};

int main()
{
     std::cout << std::boolalpha;
     std::cout << is_template<Foo>() << std::endl;  
     std::cout << is_template<TemplateFoo>() << std::endl;  
     // std::cout << is_template<MixedFoo>() << std::endl; // fails here
}

however it will fail for templates that mix non-types and types, like

template<class, int> struct MixedFoo{};

I am not able to come up with any solution, except the one in which I must explicitly specify the types in the overloads. Of course this is un-reasonable due to combinatorial explosion.

Related question (not a dupe): Is it possible to check for existence of member templates just by an identifier?

vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • 2
    Sadly [not even C++17](http://melpon.org/wandbox/permlink/VAUXmYQ6tM5L2GOh) seems to reduce the required number of combinations. – Vittorio Romeo Oct 02 '16 at 01:41

2 Answers2

6

No, there is not.

Note that template classes are not classes themselves. They are templates for classes.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • Yes, I know that template classes are not types themselves but meta types. Still, one can distinguish them from normal types, except in the case where they take non-type parameters. I thought that maybe someone can come up with a way of doing it. – vsoftco Oct 02 '16 at 00:41
  • @vsoft I added 2nd paragraph because of a minor error in your question (where you refer to a template class as a class), but mainly because first paragraph was too short for an answer. ;) – Yakk - Adam Nevraumont Oct 02 '16 at 19:42
1

I guess it is not possible.

Anyway, you can use the other way around and let N be deduced:

template<class, class> struct MixedFoo;
template<class C, int N> struct MixedFoo<C, std::integral_constant<int, N>>{};

Now, this returns true as expected:

 std::cout << is_template<MixedFoo>() << std::endl; // fails here

Of course, you won't be able anymore to use MixedFoo as MixedFoo<int, 2>, so I'm not sure it's worth it.

skypjack
  • 49,335
  • 19
  • 95
  • 187