4

我想为所有枚举定义一个运算符<<,以计算出值并打印它是这样的枚举:

代码:

enum AnyEnum{A,B,C};
AnyEnum enm = A;
cout << enm <<endl;

输出:

This is an enum which has a value equal to 0

我知道一种通过使用is_enum结构来使用 Boost 库的方法。但我不明白它是如何工作的。所以这就是为什么,一般来说,我对如何识别可验证是类类型、联合类型还是枚举(在编译时)感兴趣。

4

4 回答 4

8

确定类类型,您可以使用成员指针存在的事实

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;
};

您无法检测联合和非联合类的区别。至少我不知道怎么做,boost也不知道。

我认为检测枚举可以通过确保T不是类、函数或整数类型,然后尝试分配给整数类型来工作。你可以

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;
};

快速而肮脏的测试(适用于 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 >();
}
于 2011-01-16T12:39:13.527 回答
3

我很感兴趣如何识别可验证对象是类类型、联合类型还是枚举(在编译时)。

boost::type_traits

甚至C++ TR1也有一个<type_traits>头文件来支持该功能。在 C++0x 中,一切都会好很多。

例如,以下机器使用SFINAE来检查传递的参数是否是类类型:

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)};
};

CHECKER

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

要了解 type_traits 的工作原理,您需要具备一些模板的基本知识,包括模板元编程和 SFINAE。

于 2011-01-16T12:32:52.983 回答
0

这通常使用编译器挂钩来完成。编译器具有使用适当值“填充”模板的特殊功能(至少在 type_traits 已标准化的 C++0x 中)。例如,is_pod特征使用__is_podVC 10 下的编译器挂钩来获取适当的信息。

于 2011-01-16T12:48:46.070 回答
-3

在编译时不可能知道变量类型。

于 2011-01-16T12:30:39.620 回答