2013-03-23 154 views
13

我正在写一个类似于boost :: promote的促销模板别名,但对于C++ 11。 这样做的目的是在从varidic函数中检索参数时避免警告。例如C++ 11类型特征来区分枚举类和常规枚举

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

的促进模板别名促进以下默认参数晋升为可变参数的类型: 1)一个整数,是小于一个int被提升为int 2)浮子被提升到一倍

我的问题是,可以提升标准C++枚举,但不推荐C++ 11枚举类(编译器不会生成警告)。我想促进与常规枚举一起工作,但忽略C++ 11枚举类。

如何分辨我的Promote模板别名中的枚举类和枚举之间的区别?

+1

真正的问题是,您正在使用'va_arg's而不是'std :: initializer_list'和/或variadic模板。 – Fanael 2013-03-23 11:50:58

+0

感谢您的提示,但我有va_list,因为我正在使用C接口。 – Sam 2013-03-23 13:08:17

+0

@Sam:我的答案能解决您的问题吗? – 2013-03-24 17:14:26

回答

21

这里是一个可能的解决方案:

#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转换不是为范围枚举提供的。 [...]

这里是你将如何使用它的演示:

这里是一个live example

致谢:

感谢Daniel Frey您指出我之前的做法只会只要是operator +没有用户定义的超负荷工作。

+3

+1,但有一个洞穴:它只有在某些枚举类“E”的作者有** not **定义了他自己的'operator +(int,E)'时才起作用。通过添加一个'void dummy(int)'并使用'decltype(dummy(std :: declval ()))'来修复它。 – 2013-03-23 11:52:58

+1

@DanielFrey:好点。实际上,我可以使用不同的运算符,比如'^',以便不太可能干扰用户定义的运算符过载 – 2013-03-23 11:55:17

+1

@AndyProwl:或者调用带有int的函数。 – Fanael 2013-03-23 11:56:48