如何为所有Serializable子类实现C++ Setting类的模板特化
实现方案
核心思路是使用模板部分特化+类型约束匹配所有Serializable的派生类,避免直接操作抽象基类本身,完全保留模板参数T的使用方式。
C++11及以上版本(SFINAE实现)
首先修改主模板,增加匿名默认模板参数用于特化匹配:
#include <type_traits> // 基础类型通用主模板 template <typename T, typename = void> class Setting { std::string m_name; T m_defaultValue; public: T load() { if(backend.contains(m_name)) return backend.load<T>(m_name); return m_defaultValue; } void save(const T &value) { backend.save(m_name, value); } }; // Serializable派生类的部分特化实现 template <typename T> class Setting<T, typename std::enable_if<std::is_base_of<Serializable, T>::value>::type> { std::string m_name; T m_defaultValue; public: T load() { if(backend.contains(m_name)) { T val; // 实例化具体的派生类,而非抽象基类 val.deserialize(backend.load<std::string>(m_name)); return val; } return m_defaultValue; } void save(const T &value) { backend.save(m_name, value.serialize()); } };
如果使用C++17,可以简化特化的类型约束写法:
template <typename T> class Setting<T, std::enable_if_t<std::is_base_of_v<Serializable, T>>> { // 内部实现和上面一致 };
C++20版本(Concept实现,语法更简洁)
不需要修改主模板的参数结构,直接用concept做特化约束:
#include <concepts> template <typename T> concept DerivedFromSerializable = std::is_base_of_v<Serializable, T>; // 基础类型通用主模板 template <typename T> class Setting { std::string m_name; T m_defaultValue; public: T load() { if(backend.contains(m_name)) return backend.load<T>(m_name); return m_defaultValue; } void save(const T &value) { backend.save(m_name, value); } }; // Serializable派生类特化 template <DerivedFromSerializable T> class Setting<T> { std::string m_name; T m_defaultValue; public: T load() { if(backend.contains(m_name)) { T val; val.deserialize(backend.load<std::string>(m_name)); return val; } return m_defaultValue; } void save(const T &value) { backend.save(m_name, value.serialize()); } };
注意事项
- 自定义可序列化类型必须公开继承
Serializable,否则类型约束不会命中 - 自定义派生类必须提供可访问的默认构造函数,用于
load方法中构造初始实例 - 使用时直接传入具体派生类作为模板参数即可,编译器会自动匹配对应实现:
// 自定义派生类示例 class MyCustomConfig : public Serializable { public: int configVal = 0; std::string serialize() const override { return std::to_string(configVal); } void deserialize(const std::string &data) override { configVal = std::stoi(data); } }; // 自动匹配Serializable派生类的特化实现 Setting<MyCustomConfig> customSetting;
内容的提问来源于stack exchange,提问作者Mr. Clear
相关产品推荐
相关产品推荐

