C++如何将不带模板实参的容器类型作为模板参数使用
问题核心原因
你现在的写法里Container被定义为普通类型模板参数,但你传入的std::map是未实例化的类模板,不是完整类型,所以编译器会提示缺少模板参数。要实现你要的Registry<bool, std::map>这种用法,需要用模板模板参数:
方案1:使用模板模板参数(匹配你要的调用语法)
正确实现如下:
#include <map> #include <unordered_map> #include <type_traits> // 模板模板参数Container,接受至少2个类型参数(匹配std::map/std::unordered_map的模板参数结构) template<typename Value, template<typename, typename, typename...> typename Container, typename ID = size_t> class Registry{ // 实例化容器类型,自动兼容容器的默认后续参数(比较器、分配器等) using Storage = Container<ID, Value>; // 修正static_assert判断逻辑,检测容器是否为std::map或std::unordered_map的实例 static_assert( std::is_same_v<Storage, std::map<ID, Value>> || std::is_same_v<Storage, std::unordered_map<ID, Value>>, "Underlying storage type must be a std::map or std::unordered_map." ); public: Storage store; // 其余实现... };
现在你原来的调用代码就可以正常运行了:
Registry<bool, std::map> testRegistry; // 底层使用std::map<size_t, bool> Registry<int, std::unordered_map, uint32_t> testRegistry2; // 自定义ID类型,底层用unordered_map
方案2:直接传入完整容器类型(更灵活)
如果不需要严格限制调用语法,也可以让用户直接传入实例化完成的容器类型,扩展性更强,支持任意符合映射类接口的自定义容器:
#include <type_traits> template<typename Storage> class Registry{ // 直接从容器类型萃取ID和Value类型 using ID = typename Storage::key_type; using Value = typename Storage::mapped_type; static_assert( std::is_same_v<Storage, std::map<ID, Value>> || std::is_same_v<Storage, std::unordered_map<ID, Value>>, "Underlying storage type must be a std::map-ish." ); public: Storage store; // 其余实现... };
调用方式为:
Registry<std::map<size_t, bool>> testRegistry; Registry<std::unordered_map<uint32_t, int>> testRegistry2;
这种写法的兼容性更好,不需要处理模板模板参数的参数匹配问题,也支持用户传入自定义了比较器、哈希函数、分配器的map实例。
内容的提问来源于stack exchange,提问作者Icedude_907
相关产品推荐
相关产品推荐

