C++能否在运行时确定使用的数据类型?相关实现方案咨询
结论
C++是静态编译型语言,模板参数必须在编译期确定,你示例中直接将运行时传入的type作为模板参数实例化std::unordered_map的写法无法直接原生实现。如果要实现类似运行时选择数据类型的效果,有两种常用的落地方案:
方案1:编译期枚举所有支持类型,运行时分支选择
这种方案适合你提前知道所有可能用到的类型的场景,配合std::variant和std::visit可以写出和你示例逻辑接近的代码:
#include <unordered_map> #include <variant> #include <iostream> #include <memory> // 枚举所有支持的key/value类型 using SupportedTypes = std::variant<int, std::string, long long>; void myFunction(SupportedTypes type_tag) { std::visit([](auto&& tag) { // 提取当前传入标记的实际类型 using T = std::decay_t<decltype(tag)>; // 实例化对应类型的unordered_map auto umap = std::make_unique<std::unordered_map<T, T>>(); std::cout << "成功创建键值类型为" << typeid(T).name() << "的unordered_map\n"; // 后续可将umap存入std::any或统一基类指针对外传递 }, type_tag); } // 调用示例 int main() { myFunction(int{}); // 运行时指定创建int类型的map myFunction(std::string{}); // 运行时指定创建string类型的map return 0; }
这种方案的优势是性能损耗极低,类型安全,不需要额外做类型转换,缺点是只能支持编译期预先枚举好的类型,无法支持后续新增的未知类型。
方案2:类型擦除封装动态接口
如果需要支持完全动态、编译期无法枚举的类型,可以通过抽象基类做类型擦除,把不同类型的unordered_map的公共操作封装成统一接口:
#include <unordered_map> #include <memory> #include <any> #include <typeindex> class MapBase { public: virtual ~MapBase() = default; // 定义所有需要用到的map公共操作接口 virtual void insert(std::any key, std::any value) = 0; virtual std::any get(std::any key) const = 0; }; template<typename T> class TypeErasedMap : public MapBase { private: std::unordered_map<T, T> inner_map; public: void insert(std::any key, std::any value) override { inner_map.emplace(std::any_cast<T>(key), std::any_cast<T>(value)); } std::any get(std::any key) const override { auto it = inner_map.find(std::any_cast<T>(key)); return it != inner_map.end() ? it->second : std::any{}; } }; std::unique_ptr<MapBase> createMap(std::type_index type) { if (type == typeid(int)) { return std::make_unique<TypeErasedMap<int>>(); } else if (type == typeid(std::string)) { return std::make_unique<TypeErasedMap<std::string>>(); } // 可动态扩展其他类型分支 return nullptr; } // 调用时即可运行时传入类型 void myFunction(std::type_index type) { auto umap = createMap(type); // 后续直接调用MapBase的公共接口操作即可 }
这种方案灵活性更高,支持运行时动态判断类型创建对应实例,缺点是有一定的性能损耗,所有操作都需要做std::any_cast类型转换,且需要提前定义好所有需要用到的公共接口。
内容的提问来源于stack exchange,提问作者Victor Vector
相关产品推荐
相关产品推荐

