简体   繁体   English

如何在 enable_if 中使用多个条件?

[英]How to use multiple conditions in enable_if?

I have the following code:我有以下代码:

#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);
}

The commented line in main doesn't work and I can't figure out why. main 中的注释行不起作用,我不明白为什么。 If I pass an uint16_t to h, shouldn't the second condition enable the template?如果我将 uint16_t 传递给 h,第二个条件不应该启用模板吗? The compiler keeps complaining that it is not an enum... Why is it failing to instantiate h(uint16_t)?编译器一直抱怨它不是一个枚举……为什么它无法实例化 h(uint16_t)?

(uint16_t)1 is of type uint16_t and not an enum type, so there is no member type for underlying_type , which causes underlying_type_t to be ill-formed and aborts compilation. (uint16_t)1uint16_t类型而不是枚举类型,因此underlying_type没有成员type ,这会导致underlying_type_t格式错误并中止编译。

You can wrap is_enum_v<T> && is_same_v<underlying_type_t<T>, ...> into a separate trait and use partial specialization to apply underlying_type_t to T only when T is enum type, eg您可以将is_enum_v<T> && is_same_v<underlying_type_t<T>, ...>包装到一个单独的特征中,并使用部分特化T是枚举类型时将underlying_type_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> { };

Then isUint16ScopedEnum can be rewritten as那么isUint16ScopedEnum可以改写为

template<typename T>
using isUint16ScopedEnum = std::bool_constant<
  underlying_type_same_as<T, uint16_t>::value && !std::is_convertible_v<T, uint16_t>>;

Demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM