C ++ 11类型特征来区分枚举类和常规枚举
我正在编写一个类似于boost :: promote的升级模板别名,但是用于C ++ 11。 这样做的目的是在从varidic函数中检索参数时避免警告。 例如
template <typename T>
std::vector<T> MakeArgVectorV(int aArgCount, va_list aArgList)
{
    std::vector<T> args;
    while (aArgCount > 0)
    {
        args.push_back(static_cast<T>(va_arg(aArgList, Promote<T>)));
        --aArgCount;
    }
    return args;
}
Promote模板别名在可变参数的默认参数提升之后提升类型:1)小于int的整数提升为int 2)float提升为double
我的问题是,可以提升标准C ++枚举,但不推荐C ++ 11枚举类(编译器不会生成警告)。 我想促进与常规枚举一起工作,但忽略C ++ 11枚举类。
我如何分辨我的Promote模板别名中的枚举类和枚举之间的区别?
这是一个可能的解决方案:
#include <type_traits>
template<typename E>
using is_scoped_enum = std::integral_constant<
    bool,
    std::is_enum<E>::value && !std::is_convertible<E, int>::value>;
该解决方案利用了C ++ 11标准第7.2 / 9段中规定的范围和非范围枚举之间的行为差异:
枚举器或非范围枚举类型的对象的值通过整数提升(4.5)转换为整数。 [...]请注意,这种隐式枚举到int转换不是为范围枚举提供的。 [...]
以下是您将如何使用它的演示:
enum class E1 { };
enum E2 { };
struct X { };
int main()
{
    // Will not fire
    static_assert(is_scoped_enum<E1>::value, "Ouch!");
    // Will fire
    static_assert(is_scoped_enum<E2>::value, "Ouch!");
    // Will fire
    static_assert(is_scoped_enum<X>::value, "Ouch!");
}
这里是一个生动的例子。
致谢:
  感谢Daniel Frey指出,只要没有用户定义的operator +超载,我以前的方法就会工作。 
上一篇: C++11 type trait to differentiate between enum class and regular enum
下一篇: Are "anonymous structs" standard? And, really, what *are* they?
