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

实现爆炸猫游戏时,如何用RapidJSON获取enum class枚举值?

问题

我正在实现Exploding Kittens(爆炸猫)卡牌游戏,将卡牌类型定义为如下enum class:

enum class card_type
{
    Kitten,
    Bomb,
    ...
}

并将其作为私有变量card_type* value使用。后续在通过JSON传递事件时,希望使用RapidJSON从JSON中获取该枚举值。

我编写了如下from_json模板函数:

static serializable_value<T>* from_json(const rapidjson::Value& json) 
{
    if (json.HasMember("value")) {
        T val = json["value"].Get<T>();
        return new serializable_value<T>(val);
    }
    return nullptr;
}

并通过以下方式调用:

serializable_value<card_type>::from_json(json["value"].GetObject())

其中serializable_value是用于处理JSON的辅助类。

当使用int* value并调用serializable_value<int>::from_json(json["value"].GetObject())时代码运行正常,但使用enum class时出现报错,完整栈跟踪如下:

error: no member named 'Get' in 'rapidjson::internal::TypeHelper<rapidjson::GenericValue<rapidjson::UTF8<> >, card_type>'
    T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
                                                               ^
/src/common/game_state/cards/../../serialization/serializable_value.h:52:35: note: in instantiation of function template specialization 'rapidjson::GenericValue<rapidjson::UTF8<> >::Get<card_type>' requested here
            T val = json["value"].Get<T>();
                                  ^
/src/common/game_state/cards/card.cpp:35:80: note: in instantiation of member function 'serializable_value<card_type>::from_json' requested here
        return new card(json["id"].GetString(), serializable_value<card_type>::from_json(json["value"].GetObject()));

请问该如何处理这种本质为无符号整数的enum class类型?

解决方法

RapidJSON的Get<T>()模板默认不支持C++11的强类型枚举(enum class),因为强类型枚举不能隐式转换为整数类型。针对这个问题,有两种常用的处理方式:

方式一:手动转换整数到枚举类型

修改from_json函数,先把JSON中的值取为对应的整数类型,再显式转换为card_type。借助std::underlying_type_t<T>可以自动获取枚举的底层整数类型,不用硬编码类型,更通用:

#include <type_traits> // 需要包含此头文件

static serializable_value<T>* from_json(const rapidjson::Value& json) 
{
    if (json.HasMember("value")) {
        using UnderlyingType = std::underlying_type_t<T>;
        UnderlyingType int_val = json["value"].Get<UnderlyingType>();
        T val = static_cast<T>(int_val);
        return new serializable_value<T>(val);
    }
    return nullptr;
}

方式二:为RapidJSON特化TypeHelper模板

如果希望保持原有Get<T>()的调用方式不变,可以为card_type特化RapidJSON内部的TypeHelper模板,让它支持直接获取枚举值:

#include <type_traits>

namespace rapidjson {
namespace internal {
template<>
struct TypeHelper<GenericValue<UTF8<> >, card_type> {
    static card_type Get(const GenericValue<UTF8<> >& v) {
        using UnderlyingType = std::underlying_type_t<card_type>;
        return static_cast<card_type>(v.Get<UnderlyingType>());
    }
};
} // namespace internal
} // namespace rapidjson

特化完成后,原来的Get<card_type>()调用就能正常工作,无需修改from_json函数。

注意事项

  • 确保JSON中存储的数值与card_type定义的底层整数取值完全匹配,避免转换后出现无效的枚举值。
  • 两种方式都需要包含<type_traits>头文件以使用std::underlying_type_t。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 15:13:18