【发布时间】:2021-06-13 19:06:14
【问题描述】:
我正在创建一个同时处理许多不同用户定义类型的算法。假设这些类型中的每一个都具有func1 和func2,这将是MyAlgorithm 的接口。我可以使用可变参数模板来做到这一点:
template <typename... Args>
class MyAlgorithm{
// interact with Args using func1 and func2
};
我现在可以像 MyAlgorithm<A, B, C, D, E, F, G> 一样实例化 MyAlgorithm。这可行,但是,我觉得对于我的应用程序,这可能会导致MyAlgorithm 的专业化过多。在实践中,MyAlgorithm 可能首先被实例化,例如MyAlgorithm<A, B, B , A, C, D>,然后是MyAlgorithm<A, A, C, D>,然后是MyAlgorithm<C, F D>,以此类推。
不幸的是,模板会针对Args 的每个组合进行实例化。例如,这会在在线设置中产生问题。 MyAlgorithm 可以在批量实时输入数据上运行(MyAlgorithm 的本质是它在批量而不是单个输入上运行)。将解析实时输入数据并调用正确的 MyAlgorithm 特化。在这种情况下,用户需要在编译后的代码中创建所有可能的 MyAlgorithm 特化。
MyAlgorithm<A>;
MyAlgorithm<B>;
MyAlgorithm<C>;
MyAlgorithm<A, A>;
MyAlgorithm<A, B>;
MyAlgorithm<A, C>;
MyAlgorithm<B, A>;
...
我有一个可能会有所帮助的想法,但我并没有完全正确。代替 MyAlgorithm 获取模板参数,它将处理专门用于 A, B, Cs 的模板 Proxy 类。
// no template
class MyAlgorithm{
// interact with Proxy using func1proxy and func2proxy
std::vector<Proxy> Args;
};
template<typename T>
class Proxy{
// define func1proxy and func2proxy using Arg's func1 and func2
std::unique_ptr<T> Arg; // only member
};
当然这不起作用,因为每个Proxy 特化都是不同的类,所以MyAlgorithm 仍然需要是模板类(而std::vector<Proxy> Args 不能存在)。
有我想做的设计模式吗?是否有减少类实例化数量的设计模式?
一些注意事项:
MyAlgorithm 对所有模板参数一视同仁。该算法在每个模板参数上递归调用func1 和func2。
class MyAlgorithm{
template<typname T, typename... Args>
void CallFunc1s(T first, Args... rest){
T.func1();
SomeFunction(rest);
}
};
【问题讨论】:
-
对于这个非常常见的问题没有统包解决方案。每种情况都是独一无二的。您需要分析可以将模板的哪一部分完全分解为非模板类,以最大程度地减少代码膨胀。再多的“设计模式” Buzzword Bingo 都无法替代对代码逻辑的彻底分析和适当的重构。也许如果你清楚地重申你的问题,可以提供一个更实际的建议:你通过提到一个叫做
func和func2的东西开始你的问题,这些东西再也不会被提及。这是什么意思? -
@SamVarshavchik 重点是
MyAlgorithm只通过调用func1和func2与模板参数交互。它不与模板参数的数据成员交互,除非通过func1和func2。它 不需要知道模板参数的类型,而只需要知道如何调用该类型的func1和func2。我想象可能有一个使用函数指针的解决方案,我用的不多。特别是,如果Args之一具有func3,则不会调用func3,否则不会。 -
我不知道“与模板参数交互”是什么意思。模板参数是类型。函数参数是对象和值以及类型。无论如何,正如我所概述的,减少代码膨胀的方法是将尽可能多的代码和数据分解到非模板代码中。
-
你能把你的例子更具体一点吗?
-
您应该向我们展示一个minimal reproducible example,其中存在代码膨胀。很难在摘要中为您提供帮助。
标签: c++ templates design-patterns variadic-templates variadic-functions