【问题标题】:How to know underlying type of class enum?如何知道类枚举的基础类型?
【发布时间】:2012-03-09 17:49:46
【问题描述】:

我有一个变量声明为:

enum class FooEnum: uint64_t {}

我想转换为它的基本类型,但我不想硬编码基本类型。例如,这样的事情:

FooEnum myEnum;
uint64_t * intPointer = (underlying_typeof(myEnum))&myEnum;

这可能吗?

【问题讨论】:

  • stackoverflow.com/questions/28002/… 铸造,特别是动态
  • @L7ColWinters dynamic_cast 忍不住。不要让class 关键字和: uint64_t 误导您认为作用域枚举和枚举的底层类型类似于类继承。

标签: c++ c++11


【解决方案1】:

你可以用这个:

doc 说,

定义一个 type 的成员 typedef 类型,它是枚举 T 的基础类型。

所以你应该能够做到这一点:

#include <type_traits> //include this

FooEnum myEnum;
auto pointer = static_cast<std::underlying_type<FooEnum>::type*>(&myEnum);

【讨论】:

  • static_cast 有用吗?我的印象是没有理智的演员可以在enum class上工作。
【解决方案2】:

您猜到的语法非常接近。你在&lt;type_traits&gt;中寻找std::underlying_type

#include <type_traits>
#include <cstdint>

enum class FooEnum: std::uint64_t {};

int main()
{
    FooEnum myEnum;
    uint64_t* intPointer = (std::underlying_type<FooEnum>::type*)&myEnum;
}

【讨论】:

  • 确实如此接近。显然选择了一个合适的名字。 :)
  • 我不明白。如果intPointer 被声明为uint64_t*,那么你为什么不简单地在强制转换表达式中使用它呢?为什么还要费心使用std::underlying_type&lt;FooEnum&gt;::type*? (另外,C 风格的演员表不好,是另一个话题)。
【解决方案3】:

Visual C++ 10.0 和 MinGW g++ 4.6.1 都缺少 std::underlying_type,但都接受此代码:

template< class TpEnum >
struct UnderlyingType
{
    typedef typename conditional<
        TpEnum( -1 ) < TpEnum( 0 ),
        typename make_signed< TpEnum >::type,
        typename make_unsigned< TpEnum >::type
        >::type T;
};

【讨论】:

  • @Cheersandhth.-Alf @Grizzly:但是,TpEnum(-1)TpEnum(0) 的演员表可能有 UB:5.2.9 “静态演员表”,第 10 项说“A整数或枚举类型的值可以显式转换为枚举类型。如果原始值在枚举值范围内(7.2),则该值不变。否则,结果值未指定(并且可能不在该范围内) )。”
  • @Joker_vD: unspecified 不是 UB。
【解决方案4】:

这是当底层类型不存在时的另一种方法。这种方法不会尝试检测枚举的有符号性,只是给你一个相同大小的类型,这对于很多情况来说已经绰绰有余了。

template<int>
class TIntegerForSize
{
    typedef void type;
};

template<>
struct TIntegerForSize<1>
{
    typedef uint8_t type;
};

template<>
struct TIntegerForSize<2>
{
    typedef uint16_t type;
};

template<>
struct TIntegerForSize<4>
{
    typedef uint32_t type;
};

template<>
struct TIntegerForSize<8>
{
    typedef uint64_t type;
};

template<typename T>
struct TIntegerForEnum
{
    typedef typename TIntegerForSize<sizeof(T)>::type type;
};

用法:

enum EFoo {Alpha, Beta};
EFoo f = Alpha;
TIntegerForEnum<EFoo>::type i = f;
TIntegerForEnum<decltype(f)>::type j = f;

【讨论】:

    猜你喜欢
    • 2016-11-30
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 2013-01-13
    • 2012-09-15
    相关资源
    最近更新 更多