C++中运行时生成的整数能否作为模板参数使用?
你要实现的是运行时动态值到编译期模板参数的映射,不需要手动写switch分支,通过编译期展开自动生成跳转表即可,C++11及以上版本都支持该方案,不需要改动原有类和枚举的定义。
注意:你提供的示例代码中
Foo类模板没有继承Base,需要先补上继承关系,否则无法将Foo<i>实例的指针存入std::unique_ptr<Base>。
完整实现代码
#include <memory> #include <utility> #include <array> #include <cstdlib> class Base { }; // 补上继承关系 template<int i> class Foo : public Base { }; namespace SomeEnum { enum { First, Second, Third, Last }; } // 编译期生成所有Foo实例的工厂函数数组 template<std::size_t... Is> auto make_foo_factory(std::index_sequence<Is...>) { return std::array{ []() -> std::unique_ptr<Base> { return std::make_unique<Foo<Is>>(); }... }; } // 全局工厂表,编译阶段自动生成所有枚举值对应的实例化逻辑 constexpr auto foo_factory = make_foo_factory(std::make_index_sequence<SomeEnum::Last>{}); void bar() { std::unique_ptr<Base> ptr{ nullptr }; int fooType = rand() % SomeEnum::Last; // 运行时直接调用对应工厂即可,无需手动写分支 ptr = foo_factory[fooType](); }
方案说明
- 核心逻辑是通过
std::index_sequence生成从0到SomeEnum::Last - 1的编译期整数序列,利用可变参数展开为每个整数生成对应的lambda工厂函数,存入静态数组 - 运行时直接用拿到的
fooType作为下标调用对应工厂函数即可完成实例化,本质和手写switch的性能完全一致,属于同等级别的跳转表实现 - 后续新增枚举成员不需要改动工厂代码,只要更新
SomeEnum中Last的值,编译器会自动生成对应新枚举值的实例化逻辑 - 如果使用C++11标准,自行实现简易版
index_sequence工具类即可复用该逻辑,代码复杂度很低
内容的提问来源于stack exchange,提问作者JensB
相关产品推荐
相关产品推荐

