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

C++ C++;11用于区分枚举类和常规枚举的类型特征,c++,templates,c++11,variadic,variadic-functions,C++,Templates,C++11,Variadic,Variadic Functions,我正在为C++11编写一个类似于boost::promote的升级模板别名。 这样做的目的是在从变量函数检索参数时避免出现警告。e、 g template <typename T> std::vector<T> MakeArgVectorV(int aArgCount, va_list aArgList) { std::vector<T> args; while (aArgCount > 0) { args.pus

我正在为C++11编写一个类似于boost::promote的升级模板别名。 这样做的目的是在从变量函数检索参数时避免出现警告。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;
}
模板
std::vector MakeArgVectorV(内部aArgCount,va_列表aArgList)
{
std::向量args;
而(aArgCount>0)
{
args.push_back(静态_cast(va_arg(aarlist,Promote));
--aArgCount;
}
返回args;
}
升级模板别名升级变量参数的默认参数升级后的类型: 1) 小于整数的整数将提升为整数 2) 浮点数提升为双精度浮点数

我的问题是可以提升标准的C++枚举,但是不提倡C++ 11枚举类(编译器不生成警告)。我希望升级使用常规枚举,但忽略C++11枚举类


如何区分enum类和升级模板别名中的enum之间的区别?

以下是一种可能的解决方案:

#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>;
#包括
模板
使用is_作用域_enum=std::integral_常量<
布尔,
std::is_enum::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!");
}
enum类E1{};
枚举E2{};
结构X{};
int main()
{
//不会开火
静态断言(是范围有限的枚举::值,“哎哟!”);
//会开火吗
静态断言(是范围有限的枚举::值,“哎哟!”);
//会开火吗
静态断言(是范围有限的枚举::值,“哎哟!”);
}
这是一个例子

感谢:


感谢您指出,我以前的方法只有在没有用户定义的
操作符+

重载的情况下才有效。真正的问题是,您使用的是
va_arg
s,而不是
std::initializer\u list
和/或可变模板。谢谢您的提示,但我有va_列表,因为我正在使用它一个C接口。@Sam:我的答案能解决你的问题吗?@AndyProwl:完美的答案,正是我想要的!+1可能重复,但至少有一个洞穴:它只在某些枚举类
E
的作者没有定义自己的
操作符+(int,E)
时才起作用。通过添加一个
void dummy(int)
并使用
decltype(dummy(std::declval())
@DanielFrey:Good point来修复它。实际上,我可以使用不同的操作符,例如
^
,使其不太可能干扰用户定义的操作符overload@AndyProwl:或调用接受
int
的函数。测试转换为
int
的过程,据我所知,这是用户无法提供的。@DanielFrey:你说得对,这实际上使整个事情变得简单多了。