我有一个范围枚举:
enum class E
{ A, B, C };
现在我想要一个函数,它接受一个scoped int或int
本身的值。
应该是这样的:
template <typename T, std::enable_if_t<std::is_same<T, enum E **OR** int>::value, int> = 0 >
void foo(T value);
但我不知道如何在C ++模板中处理OR的概念。我知道std::is_convertible
,但我甚至不知道,如果我可以在这里使用它,因为你只能static_cast
将enum
范围限定为int。
但无论如何我不想接受任何可转换为int
但只能转换为单个枚举或int的类型。
答案 0 :(得分:6)
重载似乎最简单:
void foo(int value);
void foo(E value) { foo(static_cast<int>(value); } // Or specific code
template <typename T> void foo(T) = delete; // To forbid type convertible to int
否则你可以使用SFINAE
template <typename T>
std::enable_if_t<std::is_same<int, T>::value || std::is_same<E, T>::value>
foo(T value);
答案 1 :(得分:2)
由于std::is_same<...>::value
是布尔值,因此您只需使用||
运算符和2 std::is_same<...>::value
:
template <typename T, std::enable_if_t<std::is_same<T, enum E>::value || std::is_same<T, int>::value, int> = 0 >
void foo(T value);
答案 2 :(得分:1)
std::is_same
实例化定义了constexpr
隐式bool
转换,因此您可以实例化它们并使用||
执行逻辑OR。在C ++ 17中,您也可以使用std::disjunction
来达到类似的效果,尽管只有两种类型的特性可能会编译得更慢。两者的例子:
#include <type_traits>
enum class E
{ A, B, C };
template <typename T, std::enable_if_t<
std::is_same<T, E>{} || std::is_same<T, int>{},
int> = 0>
void foo(T){
}
//in C++17, you can also do this:
template <typename T, std::enable_if_t<
std::disjunction<std::is_same<T, E>, std::is_same<T, int>>{},
int> = 0>
void bar(T){
}
int main() {
foo(E::A);
foo(0);
//foo('A'); fails
bar(E::A);
bar(0);
//bar('A'); fails
return 0;
}
std::disjunction
是您想知道的逻辑OR模板(尽管我推荐||
使用std::is_same
来处理您的情况)。有趣的是,std::disjunction
甚至执行模板实例化的逻辑短路,就像简单的旧||
运算符在运行时上下文中所做的那样。我相信最新版本的libc ++已经附带std::disjunction
。如果您的<type_traits>
实现还没有,那么cppreference的示例实现对我来说就可以了。如果你有机会,你应该看看它是如何工作的。它相当聪明!