You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C++中如何将枚举类型引用转换为其底层类型的引用?

问题描述

我正在开发反序列化器,项目里有大量枚举类型,不想为每个枚举都编写deserialize重载函数,尝试将枚举类型的引用转换为其底层类型的引用,但代码无法编译,代码如下:

#include <iostream>
#include <cstdint>
#include <type_traits>
#include <cstring>


enum class MyEnum : uint32_t
{
    one = 100,
    two,
};

auto deserialize(std::byte* addr, uint32_t& val)
{
    memcpy(&val, addr, sizeof(uint32_t));
}

int main()
{
    std::byte buf[4] = { std::byte{0x00}, std::byte{0x00}, std::byte{0x00}, std::byte{0x64}};

    MyEnum val;
    
    using underlying_type = std::underlying_type_t<decltype(val)>&;
    deserialize(buf, static_cast<underlying_type>(val));

    std::cout << val << std::endl;
}
解决方案

问题原因

直接通过static_cast将枚举对象转换为其底层类型的引用是不合法的——枚举类型与底层类型属于不同类型,C++不允许这种直接的引用转换,违反类型安全规则。

修复方式

方式一:指针转换(快速修复现有代码)

先获取枚举对象的地址,转换为底层类型指针后解引用得到引用,适配现有deserialize函数:

int main()
{
    std::byte buf[4] = { std::byte{0x00}, std::byte{0x00}, std::byte{0x00}, std::byte{0x64}};

    MyEnum val;
    using Underlying = std::underlying_type_t<decltype(val)>;
    // 先转void*避免严格别名问题,再转底层类型指针并解引用
    deserialize(buf, *static_cast<Underlying*>(static_cast<void*>(&val)));

    // 强类型枚举不能直接输出,需转换为底层类型
    std::cout << static_cast<Underlying>(val) << std::endl;
}

方式二:通用模板函数(优雅解决大量枚举场景)

实现支持所有枚举类型的通用deserialize模板,从根源避免重复编写重载:

#include <iostream>
#include <cstdint>
#include <type_traits>
#include <cstring>

enum class MyEnum : uint32_t
{
    one = 100,
    two,
};

// 仅对枚举类型生效的模板函数
template<typename Enum, std::enable_if_t<std::is_enum_v<Enum>, bool> = true>
void deserialize(std::byte* addr, Enum& val)
{
    using Underlying = std::underlying_type_t<Enum>;
    memcpy(&val, addr, sizeof(Underlying));
}

// 保留基础类型的重载(若有需要)
void deserialize(std::byte* addr, uint32_t& val)
{
    memcpy(&val, addr, sizeof(uint32_t));
}

int main()
{
    std::byte buf[4] = { std::byte{0x00}, std::byte{0x00}, std::byte{0x00}, std::byte{0x64}};

    MyEnum val;
    deserialize(buf, val); // 直接传递枚举引用即可

    std::cout << static_cast<std::underlying_type_t<MyEnum>>(val) << std::endl;
}

这个模板用std::is_enum_v做约束,确保只处理枚举类型,内部直接通过memcpy将数据写入枚举对象的内存,安全且无需手动转换类型,新增枚举时无需修改反序列化逻辑。


内容的提问来源于stack exchange,提问作者glades

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:45:55