利用C++20 Concepts限制settings类方法参数类型并简化错误提示
使用C++20 Concepts限制Settings类模板参数并自定义编译错误提示
解决方案代码
#include <unordered_map> #include <variant> #include <concepts> #include <type_traits> // 定义Concept,限定仅接受long或bool类型 template<typename T> concept SettingValueType = std::same_as<T, long> || std::same_as<T, bool>; class Settings { private: std::unordered_map<std::string, std::variant<long, bool>> data_; public: // 合法类型的set方法:仅接受long或bool template<SettingValueType T> void set(const std::string& key, T value) { data_[key] = value; } // 合法类型的get_or_default方法:仅接受long或bool template<SettingValueType T> T get_or_default(const std::string& key, T default_val) const { auto it = data_.find(key); if (it != data_.end() && std::holds_alternative<T>(it->second)) { return std::get<T>(it->second); } return default_val; } // 非法类型的重载:触发自定义编译错误提示 template<typename T> requires (!SettingValueType<T>) void set(const std::string&, T) { static_assert(SettingValueType<T>, "Settings::set 仅支持 long 或 bool 类型的参数"); } template<typename T> requires (!SettingValueType<T>) T get_or_default(const std::string&, T) { static_assert(SettingValueType<T>, "Settings::get_or_default 仅支持 long 或 bool 类型的参数"); } }; // 测试示例 int main() { Settings settings; settings.set("user_age", 30L); settings.set("is_admin", true); long age = settings.get_or_default("user_age", 0L); bool is_admin = settings.get_or_default("is_admin", false); // 以下代码会触发编译错误,提示自定义信息 // settings.set("username", std::string("juan")); // settings.get_or_default("height", 180.0f); return 0; }
关键部分说明
Concept 定义
SettingValueType概念通过std::same_as精确匹配long和bool类型,确保只有这两种类型能通过约束检查。合法方法实现
带SettingValueType约束的set和get_or_default方法仅处理符合要求的类型,完成正常的存储与读取逻辑,内部利用std::variant的holds_alternative和get方法保证类型安全。自定义错误提示
针对不符合约束的类型,我们提供了专门的重载,通过requires (!SettingValueType<T>)触发匹配,内部的static_assert直接输出清晰的错误信息,替代了编译器默认的冗长模板错误,让开发者能快速定位问题。
内容的提问来源于stack exchange,提问作者Juan Medina
相关产品推荐
相关产品推荐

