如何在运行时选择已编译的不同模板参数版本的C++类实例?
如何在运行时选择已编译的不同模板参数版本的C++类实例?
当然可以啦!因为你已经明确dim只会是1或者2这两种情况,我们完全可以让编译器提前把这两个版本的MyClass都编译好,然后在运行时根据读取到的数值来选择实例化哪一个。下面给你两种常用的实现方式:
方法一:利用多态基类统一持有实例
这种方法适合需要统一接口的场景,通过一个非模板的基类来抽象不同dim版本的MyClass的公共行为:
首先定义一个基类,注意必须包含虚析构函数(否则智能指针释放时会出现未定义行为),还可以添加你需要的公共虚接口:
#include <iostream> #include <fstream> #include <memory> // 非模板基类,用于统一持有不同dim版本的MyClass class MyClassBase { public: virtual ~MyClassBase() = default; // 必须的虚析构 // 示例:添加公共虚接口 virtual void printDimInfo() const = 0; }; template <unsigned int dim> class MyClass : public MyClassBase { public: // 实现基类的虚函数 void printDimInfo() const override { if constexpr (dim == 1) { std::cout << "当前实例是MyClass<1>,数据数组长度为1" << std::endl; } else if constexpr (dim == 2) { std::cout << "当前实例是MyClass<2>,数据数组长度为2" << std::endl; } } private: double data[dim]; // 其他依赖dim的成员 }; int main() { std::fstream myfile("path_to_my_file.txt", std::ios_base::in); unsigned int dim; myfile >> dim; // 从文件读取dim,值为1或2 std::shared_ptr<MyClassBase> ptr; // 根据运行时的dim值,选择实例化对应的MyClass版本 if (dim == 1) { ptr = std::make_shared<MyClass<1>>(); } else if (dim == 2) { ptr = std::make_shared<MyClass<2>>(); } else { // 处理无效的dim值,比如抛出异常 throw std::invalid_argument("dim值只能是1或2"); } // 通过基类指针调用虚函数,实际会执行对应dim版本的实现 ptr->printDimInfo(); return 0; }
方法二:使用std::variant存储不同类型的智能指针
如果不需要统一的基类接口,或者更倾向于类型安全的变体存储,可以用C++17引入的std::variant:
#include <iostream> #include <fstream> #include <memory> #include <variant> template <unsigned int dim> class MyClass { public: void printDimInfo() const { std::cout << "当前实例是MyClass<" << dim << ">,数据数组长度为" << dim << std::endl; } private: double data[dim]; // 其他依赖dim的成员 }; int main() { std::fstream myfile("path_to_my_file.txt", std::ios_base::in); unsigned int dim; myfile >> dim; // 从文件读取dim,值为1或2 // 定义variant,只能存储MyClass<1>或MyClass<2>的智能指针 std::variant<std::shared_ptr<MyClass<1>>, std::shared_ptr<MyClass<2>>> var_ptr; if (dim == 1) { var_ptr = std::make_shared<MyClass<1>>(); } else if (dim == 2) { var_ptr = std::make_shared<MyClass<2>>(); } else { throw std::invalid_argument("dim值只能是1或2"); } // 使用std::visit访问variant中的对象 std::visit([](const auto& ptr) { // 这里ptr的类型会自动推导为对应的shared_ptr<MyClass<1>>或shared_ptr<MyClass<2>> ptr->printDimInfo(); }, var_ptr); return 0; }
原理说明
因为你已经限定了dim只有1和2两个可能值,编译器会在编译时为这两个分支分别生成MyClass<1>和MyClass<2>的完整代码。运行时只需要根据读取到的dim值,选择进入对应的分支创建实例即可,完全符合你的需求。
备注:内容来源于stack exchange,提问作者SolidMechanicsFan
相关产品推荐
相关产品推荐

