C++ std::conditional_t 不会用 std::is_enum_v 和 std::underlying_type_t 编译

标签 c++ metaprogramming typetraits

我正在尝试为可以索引的类型编写类型特征,例如std::vector ,它应该包括枚举类型,因为我可以将它们转换为它们的基础类型。
到目前为止,我已经写了以下特征。

#include <iostream>
#include <type_traits>
#include <cinttypes>
#include <vector>
#include <utility>

template<typename T>
struct is_unsigned_integral :
    std::integral_constant<
        bool,
        std::is_integral<T>::value &&
        std::is_unsigned<T>::value
    > {};

template<typename T>
inline constexpr auto is_unsigned_integral_v = 
    is_unsigned_integral<T>::value;

template<typename, typename = void>
struct is_index : std::false_type {};

template<typename T>
struct is_index<
    T, 
    std::enable_if_t<
        is_unsigned_integral_v<
            std::conditional_t<
                std::is_enum_v<T>,
                std::underlying_type_t<T>,
                T
            >
        >
    >
> : std::true_type {};

template<typename T>
inline constexpr auto is_index_v = is_index<T>::value;

enum class idx : unsigned int {};

int main() {
    static_assert(is_index_v<unsigned int>, "");
    static_assert(is_index_v<idx>, "");
    
    return 0;
}
但我收到以下错误消息
type_traits:2009:15: error: 
      only enumeration types have underlying types
      typedef __underlying_type(_Tp) type;
我希望以下
std::conditional_t<
    std::is_enum_v<T>,
    std::underlying_type_t<T>,
    T
>
评估八至 T或底层类型是 Tenum .
我将如何使这项工作?

最佳答案

替换失败,因为没有 std::underlying_type_t<unsigned int> .
您可以单独专攻:

#include <iostream>
#include <type_traits>
#include <cinttypes>
#include <vector>
#include <utility>

template<typename T>
struct is_unsigned_integral :
    std::integral_constant<
        bool,
        std::is_integral<T>::value &&
        std::is_unsigned<T>::value
    > {};

template<typename T>
inline constexpr auto is_unsigned_integral_v = 
    is_unsigned_integral<T>::value;

template<typename, typename = void>
struct is_index : std::false_type {};

template<typename T>
struct is_index<
    T, 
    std::enable_if_t< is_unsigned_integral_v<T> >    
> : std::true_type {};

template <typename T>
struct is_index<T,std::enable_if_t<std::is_enum_v<T> >> : is_index<std::underlying_type_t<T> > {};


template<typename T>
inline constexpr auto is_index_v = is_index<T>::value;

enum class idx : unsigned int {};

int main() {
    static_assert(is_index_v<unsigned int>, "");
    static_assert(is_index_v<idx>, "");
    
    return 0;
}

PS:来自 cppreference/std::underlying_type

If T is a complete enumeration (enum) type, provides a member typedef type that names the underlying type of T.

Otherwise, the behavior is undefined. (until C++20)

Otherwise, if T is not an enumeration type, there is no member type. Otherwise (T is an incomplete enumeration type), the program is ill-formed. (since C++20)


我不得不承认,我不确定在您的示例中未定义的行为(在 C++20 之前)如何与 SFINAE 一起使用。不过,请注意,上面这不是问题,因为它只使用 std::underlying_type_t<T>T实际上是一个枚举类型。

关于C++ std::conditional_t 不会用 std::is_enum_v 和 std::underlying_type_t 编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69284927/

相关文章:

c++ - 使用 packaged_task 和线程的可能数据竞争

c++ - 在编译时检测 C++ 代码中的重复工作

c++ - 为 type_traits 类创建一个 "negate"包装器

c++ - 从 libcurl 为 HTTP POST 计算 Content-MD5

c++ - 需要在 C++ 中找到两个 XML 文件之间的区别

c++ - C++中的多重继承,它看起来像菱形,但实际上不是

python - 通过方法装饰器修改类属性

c++ - 为什么同时具有默认析构函数和 vector 成员会阻止类成为 "nothrow movable constructible"?

c++ - 如何检查给定类型的变量是否可以取消引用?