【发布时间】:2019-11-23 13:36:19
【问题描述】:
我正在使用由其他人编写的 C++ 库(不幸的是,imo)实现了几种封装在类中的算法,其行为可以通过作为模板参数传递的参数进行微调(参数通常也是类)。因此,例如可能有这样的类模板:
template<typename Param1, typename Param2, typename Param3>
class Foo {
// ...
};
我想使用这个库编写一个程序,该程序需要根据运行时信息创建Foo 的实例。我的问题是,假设有N1、N2 和N3 可以为Param1、Param2 和Param3 传递的有效类型,我可能需要创建最多N1 x N2 x N3 分支当我想实例化Foo 的不同特殊化时,我的代码中的某个点。例如,假设我在运行时通过用户输入获得三个字符串,每个字符串决定Foo 的模板参数之一应该是哪种类型,那么我需要做这样的事情:
std::string s1, s2, s3;
// instantiate s1, s2, s3 from user input
if (s1 == "Param1_1" && s2 == "Param2_1" && s3 == "Param3_1") {
Foo<Param1_1, Param2_1, Param3_1> foo;
} else if (s1 == "Param1_1" && s2 == "Param2_1" && s3 == "Param3_2") {
Foo<Param1_1, Param2_1, Param3_2> foo;
}
// ...
其中Param1_1 是Param1 的有效类型等等。我怎样才能更优雅地实现这一点? (理想情况下只使用 C++11 或最多 C++17 功能)。
【问题讨论】:
-
更优雅?我没有看到如何手动编写所有这些组合的方法,最多可以缩短使用某些宏编写的代码,但如果 that 更“优雅”是值得怀疑的。不过,比这个可能很长的 if/else 链快可能是散列:
std::unordered_map<std::string, void(*)(/* parameters as needed */),您可能会用一些 lambdas 填充它,例如map["Param1_1\x1FParam2_1\x1FParam3_1"] = [](/*...*/) { Foo<Param1_1, Param2_1, Param3_1> foo; /* ... */ };。 -
旁注:0x1f 是 ASCII 单位分隔符,如果您愿意,请选择另一个,但用户很难在键盘上输入...
-
jit proposal 可能会让您感兴趣。即使您仍然必须进行调度。
-
我会选择简单的东西。只需将
if之后的所有内容放入一个通用 lambda,然后使用foo调用它。喜欢auto continuation = [&, this](auto foo) { ... }; if(...) { continuation(Foo<Param1_1, Param2_1, Param3_1>()); } else if(...) { continuation(Foo<...>()); } ...。对于 C++11,去掉 lambda 并将其放入模板(成员)函数中。