20

我正在尝试实施std::is_enum. 到目前为止,这是我的代码:

template<typename T>
struct is_enum {
    static bool value;
};

template<typename T>
bool is_enum<T>::value = false;

template<enum E>
struct is_enum {
    static bool value;
};

template<enum E>
bool is_enum<E>::value = true;

此代码会导致错误。更确切地说:

g++ -std=c++0x -Wall -o "enum2" "enum2.cpp" (in directory: /home/aristophanes/Desktop/C++)
Compilation failed.
enum2.cpp:11:15: error: use of enum ‘E’ without previous declaration
enum2.cpp:3:10: error: template parameter ‘class T’
enum2.cpp:12:8: error: redeclared here as ‘int E’
enum2.cpp:16:15: error: use of enum ‘E’ without previous declaration
enum2.cpp:17:14: error: ‘E’ was not declared in this scope
enum2.cpp:17:15: error: template argument 1 is invalid
enum2.cpp:17:18: error: template declaration of ‘bool value’

谁能向我解释我在哪里犯了错误?是我的错还是编译器的错?提前致谢。

编辑:如果完全错误,那我该如何纠正呢?

注意:我正在使用g++ -o <file> <file>.cpp

4

3 回答 3

18

实现这一点的最好方法是使用编译器魔法,我相信大多数实现都是这样做的。

例如,这里是 gcc >= 4.3 和任何编译器的 libc++ 实现__has_feature(is_enum)1

template <class _Tp> struct _LIBCPP_VISIBLE is_enum
    : public integral_constant<bool, __is_enum(_Tp)> {};



对于所有其他编译器,libc++ 会:

template <class _Tp> struct _LIBCPP_VISIBLE is_enum
    : public integral_constant<bool, !is_void<_Tp>::value             &&
                                     !is_integral<_Tp>::value         &&
                                     !is_floating_point<_Tp>::value   &&
                                     !is_array<_Tp>::value            &&
                                     !is_pointer<_Tp>::value          &&
                                     !is_reference<_Tp>::value        &&
                                     !is_member_pointer<_Tp>::value   &&
                                     !is_union<_Tp>::value            &&
                                     !is_class<_Tp>::value            &&
                                     !is_function<_Tp>::value         > {};

其中一些其他类型特征仍然需要编译器魔法。2例如is_union。但是,可以重写该条件,使其不需要编译器魔法。正如 Johannes Schaub 指出的那样,这可以通过将联合和类的单独检查替换为两者的单一检查来完成。

__has_feature1.不幸的是,据我所知,只有 clang 工具。
2. 有趣的是,libc++ 确实有一个不使用编译器内在函数的版本is_union<T>is_class<T>但结果它们为联合类型提供了错误的结果。但是它们的错误结果是互补的,因此 libc++ 的后备实现is_enum<T>提供了准确的结果。

于 2012-07-03T19:00:17.687 回答
9

template<enum E>

承诺模板参数是type的enum E。该参数不是类型(类型模板参数由 引入typename,或者为了向后兼容,class. Evenstruct是不允许的)。这就像说

template<int i>

除了没有为变量指定名称。

事情从那里开始出错。

于 2012-07-03T18:28:11.333 回答
2

你的问题是

template<enum E>

被解释为类型为前向声明的枚举命名的未命名参数E
语义相同

template<int>

只需替换intenum E.

于 2012-07-03T18:29:41.803 回答