【发布时间】:2017-03-27 12:08:27
【问题描述】:
TL;DR:寻找预处理器宏来为模板参数的预定义集/枚举的所有组合生成所有if/else-if/else-error 语句。
我有一个抽象类(Base)的 3 个子类(SubA<int a>、SubB<int a>、SubC<int a, int b>),所以我无法初始化抽象类但可以初始化子类。这些子类也有一个或两个非类型模板参数。
class Base {...}; // abstract
class SubA<int a> : public Base {...};
class SubB<int a> : public Base {...};
class SubC<int a, int b> : public Base {...};
我有一个基准测试工具,它从数据库中提取不同的基准测试配置(要运行的子类、模板参数和参数/工作负载)。模板参数是确定集(a in {256, 512, 1024, 2048, 4096, 8192, 16384} 和 b in {1, 2, 3})。
我希望能够将Base 对象实例化为具有正确模板参数的子类,而不必if/else if 所有可能性/组合。在 C++ 中是否有一种干净的方法可以使用枚举、数组甚至预处理器宏来执行此操作?
一个冗长的方法是有许多 if-else 语句,但我想要一个更简洁的解决方案,如果可能的话,将值从枚举、集合或数组中提取出来。肯定有生成组合的预处理器方式,或者从枚举中选择的方式(因此编译器创建所有枚举组合的类)?
Base *base = nullptr;
if (sub == "SubA") {
if (a == 512) {
if (b == 1) {
base = new SubA<512, 1>();
} else if (b == 2) {
base = new SubA<512, 2>();
} else if (b == 3) {
base = new SubA<512, 3>();
}
} else if (a == 1024) {
// ...
}
} else if (sub == "SubB") {
// ...
} else if (sub == "SubC") {
// ...
}
if (base == nullptr) {
throw std::exception();
}
作为进一步的解释,这里有一个用 JS 编写的等效解决方案:
class Base = {...};
function SubAFactory(a, b) = {return class SubA {... definition ...}};
function SubBFactory(a, b) = {return class SubB {... definition ...}};
function SubCFactory(a, b) = {return class SubC {... definition ...}};
const SubFactories = {
SubA: SubAFactory,
SubB: SubBFactory,
SubC: SubCFactory
};
function BaseFactory(sub, a, b) {
// NOTE: an if-else between subclasses would also be fine
// as long as the template args are "dynamic".
return SubFactories[sub](a, b);
}
// retrieved from db at runtime, a and b values will
// always be part of a finite set known at compile time
const dbResult = {sub: 'SubA', a: 2048, b: 2};
const sub = dbResult.sub;
const a = dbResult.a;
const b = dbResult.b;
const base = new BaseFactory(sub, a, b)(/* class constructor args */);
【问题讨论】:
-
你不能在运行时做任何与模板相关的事情,这是一个仅在编译时的功能。
-
你可以,但它需要一个非常大的开关。编辑:取决于可能的模板实例化的数量,它可以用黑魔法(宏)来完成,但你可能想找到另一个解决方案
-
但是我在编译时知道所有可能的值,所以编译器必须有办法从集合中提取这些可能的值并为排列创建类?还是在预处理器宏中执行此操作的好方法?
-
好的,传入递归宏奥术
-
如果
sub、a和b中的任何 在运行时被初始化或设置,那么真的没有办法将它们用于模板。我能想到的唯一可行的解决方案不是条件语句(if或switch)是使用映射或类似的东西来实例化所有类。或者重新设计。
标签: c++ templates factory-pattern