C ++ 11类型特征来区分枚举类和常规枚举 [英] C++11 type trait to differentiate between enum class and regular enum

查看:258
本文介绍了C ++ 11类型特征来区分枚举类和常规枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个类似于boost :: promote但是对于C ++ 11的促销模板别名。
这是为了避免在从varidic函数中检索参数时发出警告。例如

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的整数被提升为int
2)一个float被提升为double

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枚举类(编译器不会生成警告)。我想让Promote使用常规枚举,但忽略一个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.

如何区分enum类和枚举在我的Promote模板别名?

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的第7.2 / 9节中指定的范围和未范围枚举之间的行为差​​异++ 11标准:

The solution exploits a difference in behavior between scoped and unscoped enumerations specified in Paragraph 7.2/9 of the C++11 Standard:


无范围枚举类型的枚举器或对象的值通过整数提升转换为整数)。 [...]请注意,不为范围枚举提供此隐式枚举到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!");
}

这是一个实例

ACKNOWLEDGMENTS:

感谢 Daniel Frey 指出,我以前的方法只有在没有用户定义的运算符+ 的重载

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 +.

这篇关于C ++ 11类型特征来区分枚举类和常规枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆