5

How to check using some template hack whether a template argument passed is of class type?

Example

int main()
{
   CheckIfClass<int>::checkConst ; No it is not of a class type
   class CLASS{};
   CheckIfClass<CLASS>::checkConst ; Yes CLASS is a class.
   CheckIfClass<std::string>::checkConst ; Yes std::string is a class
}
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
NEWBIE
  • 53
  • 3

3 Answers3

7

SFINAE should do your job

#include <iostream>
template<typename T>
struct Check_If_T_Is_Class_Type
{
    template<typename C> static char func (char C::*p);
    template<typename C> static int func (...);
    enum{val = sizeof (Check_If_T_Is_Class_Type<T>::template func<T>(0)) == 1};
};
class empty{}; // Defined the class in the global namespace. 
               // You can't have local classes as template arguments in C++03

int main()
{

    std::cout<<Check_If_T_Is_Class_Type<empty>::val; // 1
    std::cout<<Check_If_T_Is_Class_Type<int>::val; // 0
    std::cout<<Check_If_T_Is_Class_Type<std::string>::val; //1
}

Output

101
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • @UpVoter : Oh ideone compiled the code in c++0x mode. Updated my answer (for C++03). – Prasoon Saurav Dec 04 '10 at 06:46
  • Wow! I need to figure out how the code is actually working. thanks. – NEWBIE Dec 04 '10 at 06:51
  • @Nawaz : Yes it is optional :-) – Prasoon Saurav Dec 04 '10 at 07:36
  • @Prasoon Saurav... your code doesn't compile with MSVC++2008. What's wrong with it? `'char Check_If_T_Is_Class_Type::func(char C::* )' : could not deduce template argument for 'char C::* ' from 'int' 'int Check_If_T_Is_Class_Type::func(...)' : could not deduce template argument for 'C'` – Nawaz Dec 04 '10 at 10:32
  • @Nawaz : The code gets compiled on Comeau, g++ and Clang. MSVC++ as we all know is buggy. You can create another thread asking for an explanation why this doesn't get compiled on MSVC++. There are so many MS guys out there. :-) – Prasoon Saurav Dec 04 '10 at 10:41
  • @Nawaz: It would seem to compile if you remove `Check_If_T_Is_Class_Type::template` (should be superfluous anyway?) – UncleBens Dec 04 '10 at 10:44
  • @UncleBens... yeah I was trying to do those sort of things and eventually discovered it gets compiled if I remove `template` ketyword. I've posted the solution! – Nawaz Dec 04 '10 at 11:58
2

C++0x offers a very simple solution:

#include <iostream>
#include <type_traits>

int main()
{
    std::cout << is_class< your_type_here >::value << std::endl;
}
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
1

Code that compiles with MSVC++08 ALSO, as well as with GCC, Comeau, and Clang (edited).

#include <iostream>
template<typename T>
struct Check_If_T_Is_Class_Type
{
    template<typename C> static char func (char C::*p);
    template<typename C> static int func (...);
    enum{val = sizeof (func<T>(0)) == 1};
};
class empty{};
int main()
{   
    std::cout<<Check_If_T_Is_Class_Type<empty>::val; // 1
    std::cout<<Check_If_T_Is_Class_Type<int>::val; // 0
    std::cout<<Check_If_T_Is_Class_Type<std::string>::val; //1
}

@Prasoon... could you please compile this on Comeau, and Clang ... and tell me if it gets compiled or not? thanks!

Nawaz
  • 353,942
  • 115
  • 666
  • 851