如何在enable_if中使用多个条件?
How to use multiple conditions in enable_if?
我有以下代码:
#include <iostream>
#include<type_traits>
using namespace std;
enum class a : uint16_t
{
x, y
};
template<typename T>
using isUint16ScopedEnum = std::integral_constant<
bool,
std::is_enum_v<T> && std::is_same_v<std::underlying_type_t<T>, uint16_t> && !std::is_convertible_v<T, uint16_t>>;
template<typename T, std::enable_if_t<is_same_v<T, uint16_t>, void**> = nullptr>
void f(T t)
{
cout << "works\n";
}
template<typename T, std::enable_if_t<isUint16ScopedEnum<T>::value, void**> = nullptr>
void g(T t)
{
cout << "also works\n";
}
template<typename T, std::enable_if_t<isUint16ScopedEnum<T>::value || is_same_v<T, uint16_t>, void**> = nullptr>
void h(T t)
{
cout << "Works with enum, Fails with uint\n";
}
int main()
{
a A = a::x;
f((uint16_t)1);
g(A);
h(A);
//h((uint16_t)1);
}
main 中的注释行不起作用,我不明白为什么。如果我将 uint16_t 传递给 h,第二个条件不应该启用模板吗?编译器一直抱怨它不是一个枚举...为什么它无法实例化 h(uint16_t)?
(uint16_t)1
是 uint16_t
类型而不是枚举类型,因此 underlying_type
没有成员 type
,这导致 underlying_type_t
是ill-formed 并中止编译。
您可以将 is_enum_v<T> && is_same_v<underlying_type_t<T>, ...>
包装到一个单独的特征中,并使用部分特化将 underlying_type_t
应用于 T
仅当 T
时 ] 是枚举类型,例如
template<typename E, class T, bool = std::is_enum_v<E>>
struct underlying_type_same_as;
template<typename E, class T>
struct underlying_type_same_as<E, T, false> : std::false_type { };
template<typename E, class T>
struct underlying_type_same_as<E, T, true>
: std::is_same<std::underlying_type_t<E>, T> { };
那么isUint16ScopedEnum
可以改写为
template<typename T>
using isUint16ScopedEnum = std::bool_constant<
underlying_type_same_as<T, uint16_t>::value && !std::is_convertible_v<T, uint16_t>>;
我有以下代码:
#include <iostream>
#include<type_traits>
using namespace std;
enum class a : uint16_t
{
x, y
};
template<typename T>
using isUint16ScopedEnum = std::integral_constant<
bool,
std::is_enum_v<T> && std::is_same_v<std::underlying_type_t<T>, uint16_t> && !std::is_convertible_v<T, uint16_t>>;
template<typename T, std::enable_if_t<is_same_v<T, uint16_t>, void**> = nullptr>
void f(T t)
{
cout << "works\n";
}
template<typename T, std::enable_if_t<isUint16ScopedEnum<T>::value, void**> = nullptr>
void g(T t)
{
cout << "also works\n";
}
template<typename T, std::enable_if_t<isUint16ScopedEnum<T>::value || is_same_v<T, uint16_t>, void**> = nullptr>
void h(T t)
{
cout << "Works with enum, Fails with uint\n";
}
int main()
{
a A = a::x;
f((uint16_t)1);
g(A);
h(A);
//h((uint16_t)1);
}
main 中的注释行不起作用,我不明白为什么。如果我将 uint16_t 传递给 h,第二个条件不应该启用模板吗?编译器一直抱怨它不是一个枚举...为什么它无法实例化 h(uint16_t)?
(uint16_t)1
是 uint16_t
类型而不是枚举类型,因此 underlying_type
没有成员 type
,这导致 underlying_type_t
是ill-formed 并中止编译。
您可以将 is_enum_v<T> && is_same_v<underlying_type_t<T>, ...>
包装到一个单独的特征中,并使用部分特化将 underlying_type_t
应用于 T
仅当 T
时 ] 是枚举类型,例如
template<typename E, class T, bool = std::is_enum_v<E>>
struct underlying_type_same_as;
template<typename E, class T>
struct underlying_type_same_as<E, T, false> : std::false_type { };
template<typename E, class T>
struct underlying_type_same_as<E, T, true>
: std::is_same<std::underlying_type_t<E>, T> { };
那么isUint16ScopedEnum
可以改写为
template<typename T>
using isUint16ScopedEnum = std::bool_constant<
underlying_type_same_as<T, uint16_t>::value && !std::is_convertible_v<T, uint16_t>>;