区分枚举类和常规枚举的 C++11 类型特征

标签 c++ templates c++11 variadic variadic-functions

我正在为 C++11 编写类似于 boost::promote 的促销模板别名。 这样做的目的是避免在从可变函数检索参数时出现警告。例如

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 枚举类。

如何区分枚举类和提升模板别名中的枚举?

最佳答案

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

#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 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. [...]

以下是您如何使用它的演示:

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!");
}

这里是 live example .

致谢:

感谢 Daniel Frey指出我以前的方法只有在没有用户定义的 operator + 重载时才有效。

关于区分枚举类和常规枚举的 C++11 类型特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15586163/

相关文章:

c++ - 模板类对象的比较器,C++

c# - 是否有在现有模板中添加 css 模板的解决方案?

c++ - 使用默认构造函数在 vector 中放置

c++ - move 是否会使对象处于可用状态?

c++ - 在这个简单的例子中,为什么 std::optional 的赋值运算符不能用于编译时上下文?

c++ - 这是在 C++ 中执行 "with"语句的最佳方法吗?

c++ - Visual Studio 中的字符集是什么?

c++ - 更新文件中的记录 (c++)

c++ - 如何在已执行的方法中传递字段的值?

c++ - 为二维 vector 类创建标量乘法运算符