C++11 类型特征来区分枚举类和常规枚举
我正在编写类似于 boost::promote 的促销模板别名,但适用于 C++11.这样做的目的是避免在从可变函数中检索参数时出现警告.例如
I'm writing a promotion template alias similar to boost::promote but for C++11. The purpose of this is to avoid warnings when retrieving arguments from varidic functions. e.g.
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 的整数被提升为 int2) 浮点数提升为双倍
The Promote template alias promotes the type following the default argument promotion for variadic arguments: 1) An integer that's smaller than an int is promoted to int 2) A float is promoted to double
我的问题是可以提升标准 C++ 枚举,但不提升 C++11 枚举类(编译器不会生成警告).我希望提升使用常规枚举但忽略 C++11 枚举类.
My problem is that a standard C++ enum can be promoted but a C++11 enum class is not promoted (compiler does not generate a warning). I want Promote to work with a regular enum but ignore a C++11 enum class.
如何区分我的提升模板别名中的枚举类和枚举?
How can I tell the difference between an enum class and an enum in my Promote template alias?
推荐答案
这是一个可能的解决方案:
Here is a possible solution:
#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 段中指定的作用域枚举和非作用域枚举之间的行为差??异:
The solution exploits a difference in behavior between scoped and unscoped enumerations specified in Paragraph 7.2/9 of the C++11 Standard:
枚举数或无作用域枚举类型的对象的值通过整数提升 (4.5) 转换为整数.[...] 请注意,不为作用域枚举提供此隐式枚举到 int 转换.[...]
The value of an enumerator or an object of an unscoped enumeration type is converted to an integer by integral promotion (4.5). [...] Note that this implicit enum to int conversion is not provided for a scoped enumeration. [...]
以下是如何使用它的演示:
Here is a demonstration of how you would use it:
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 +
的定义重载.
Thanks to Daniel Frey for pointing out that my previous approach would only work as long as there is no user-defined overload of operator +
.
相关文章