【发布时间】:2014-02-22 10:42:32
【问题描述】:
在我经常使用模板元编程的软件中,模板类通常将类模板作为参数来定义其行为的某些方面。作为一个非常简单的例子,假设我们有一个类FormulaUser,它需要使用一个公式从其他两个数字中计算出一个数字,并且必须将特定的公式指定为模板参数。此外,该公式需要针对其操作的数据类型(浮点数或双精度数)开放。例如:
template <template<typename> class Formula, typename FpType>
struct FormulaUser {
using TheFormula = Formula<FpType>;
void some_function ()
{
FpType x = 1;
FpType y = 2;
FpType result = TheFormula::calculate(x, y);
}
};
template <typename FpType>
struct AddFormula {
static FpType calculate (FpType x, FpType y) { return x + y; }
};
// composition:
using TheFormulaUser = FormulaUser<AddFormula, float>;
这没关系,但当公式本身需要在传递给FormulaUser 之前定义参数时,就不行了。比如一个LinearFormula(让我们忽略浮点类型不能是模板参数的事实):
template <float A, float B, float C>
struct LinearFormula {
template <typename FpType>
struct Formula {
static FpType calculate (FpType x, FpType y) { return A + B*x + C*y; }
};
};
// composition:
using TheFormulaUser = FormulaUser<LinearFormula<1.0, 2.0, 3.0>::template Formula, float>;
我不喜欢这段代码的地方是:
- 构图很丑(
::template Formula part)。 -
LinearFormula的肉缩进了两次。
有什么方法可以让它变得更好?
更新
我希望将公式参数分成两个级别(公式常量和 FpType)的原因是第一组中的那些是用户配置的一部分,而第二组中的那些是由正在制作的类提供的公式的使用。好吧,FpType 也最终作为用户配置,但它应该对所有公式都相同。这个更复杂的组合证明了这一点......
using MyProgram = Program<
float, // FpType
AddFormula, // Formula for something
LinearFormula<2.0, 5.3, 5.3>, // Formula for something else
QuadraticFormula<.....>, // For something else...
ExponentialAveraging< // AveragingType
0.6 // SmoothingFactor
>
>;
因此,您将 FpType 提供给根类,然后将其传播到其他所有内容。
这些例子是人为的,但它们应该能解释问题。我不希望配置有比必要更多的样板文件(特别是,不能像上面那样真正指定浮点常量......)。
最后,需要使用模板元编程(出于性能原因以及与现有代码的一致性)。
【问题讨论】:
-
双缩进和
::template是嵌套的结果,但是您没有激发嵌套,甚至没有提供有效的说明。解决方案显然是避免嵌套,但鉴于此信息,我们无法帮助解决该问题。 -
@Potatoswatter 查看更新
-
您似乎处于表达式模板所解决的解决方案空间中。您可能会研究这些是如何完成的。组合是通过函数重载,而不是嵌套的模板参数列表。无论如何,这只是我的风格,但不管 TMP 的复杂性如何,我个人都避免将模板模板参数暴露给用户。几乎总是有更好的选择。
标签: c++ composition template-meta-programming boilerplate