How to know if the argument that is passed to the function is a class, union or enum in c++?

ぃ、小莉子 提交于 2019-12-01 00:49:24

Determining class types you could use the fact that member pointers exist

template<typename A, typename B>
struct issame { };

template<typename A>
struct issame<A, A> { typedef void type; };

template<typename> struct tovoid { typedef void type; };

template<typename T, typename = void>
struct isclass { static bool const value = false; };

template<typename C>
struct isclass<C, typename tovoid<int C::*>::type> {
  static bool const value = true;
};

You cannot detect the difference of an union and a non-union class. At least I don't know how, and boost doesn't know either.

I think detecting enums could work by making sure T isn't a class, function or integral type, and then trying to assign to an integral type. You could

template<typename E, typename = void> 
struct isenum { 
  struct No { char x; };
  struct Yes { No n1; No n2; };

  struct nullsink {};
  static No checkI(nullsink*); // accept null pointer constants
  static Yes checkI(...);

  static Yes checkE(int);
  static No checkE(...);

  static bool const value = (sizeof(checkI(E())) == sizeof(Yes)) && 
                            (sizeof(checkE(E())) == sizeof(Yes));
};

// class
template<typename E>
struct isenum<E, typename tovoid<int E::*>::type> {
  static bool const value = false;
};

// reference
template<typename R>
struct isenum<R&, void> {
  static bool const value = false;
};

// function (FuntionType() will error out).
template<typename F>
struct isenum<F, typename issame<void(F), void(F*)>::type> {
  static bool const value = false;
};

// array (ArrayType() will error out)
template<typename E>
struct isenum<E[], void> {
  static bool const value = false;
};
template<typename E, int N>
struct isenum<E[N], void> {
  static bool const value = false;
};

Quick & dirty test (works on GCC/clang/comeau):

enum A { };
struct B { };
typedef int &C;
typedef void D();
typedef int E;
typedef long F;
typedef int const G;
typedef int H[1];

template<typename T, bool E>
struct confirm { typedef char x[(T::value == E) ? 1 : -1]; };

int main() {
  confirm< isenum<A>, true >();
  confirm< isenum<B>, false >();
  confirm< isenum<C>, false >();
  confirm< isenum<D>, false >();
  confirm< isenum<E>, false >();
  confirm< isenum<F>, false >();
  confirm< isenum<G>, false >();
  confirm< isenum<H>, false >();
}

I am interested how to identify if the veriable is a class type, union type or an enum (in compile time).

boost::type_traits

Even C++ TR1 has got a <type_traits> header to support that functionality. In C++0x everything's gonna be a lot better.

For example the following machinery makes use of SFINAE to check whether the argument passed is a class type:

template<typename T>struct Check_If_T_Is_Class_Type
{
    template<typename C> static char func (char C::*p);
    template<typename C> static long func (...);
    enum{val = CHECKER(func,Check_If_T_Is_Class_Type)};
};

The MACRO CHECKER is

#define CHECKER(func_name,class_name) \
sizeof(class_name<T>::template func_name<T>(0)) == 1

To understand how type_traits work you need to have some basic knowledge of templates including template metaprogramming and SFINAE.

This is usually done with compiler hooks. The compiler has special functions that "fill" the template with the apropriate value (at least in C++0x where type_traits has been standardized). For instance the is_pod trait uses the __is_pod compiler hook under VC 10 to get the apropriate information.

its not possible to know the variable type at compile time.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!