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

如何为所有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());
    }
};

注意事项

  1. 自定义可序列化类型必须公开继承Serializable,否则类型约束不会命中
  2. 自定义派生类必须提供可访问的默认构造函数,用于load方法中构造初始实例
  3. 使用时直接传入具体派生类作为模板参数即可,编译器会自动匹配对应实现:
// 自定义派生类示例
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 19:27:04