避免模​​板扩散

时间:2015-04-24 17:16:09

标签: c++ templates

我正在研究一个相当紧密耦合的库,到目前为止已明确假设所有计算都是用双精度完成的。我正在将一些核心类转换为模板,以便我们可以使用std::complex<double>开始计算。到目前为止,我已经注意到我们的课程中有10个已经注意到模板扩散的趋势。当一个类变成模板时,使用模板化类的任何其他类似乎也需要模板化。我想我可以通过为我的模板定义抽象基类来避免这种扩散,这样其他类就可以使用指向抽象类的指针,然后引用派生的doublestd::complex<double>版本类。这似乎在标题级别起作用,但是当我深入研究源文件时,模板化的类通常会具有计算类型doublestd::complex<double>值的值或容器的函数。模拟整个类似乎是浪费,因为源文件中的几行是不同的,因为其他类返回类型。

使用auto似乎是一种解决此问题的可能方法,但我并非100%确定它会起作用。假设我有AbstractFunction派生的抽象基类Function<Scalar>,其中Scalar可以是doublestd::complex<double>。现在假设我们有两个成员函数:

virtual Scalar Function<Scalar>::value(double x);
virtual void Function<Scalar>::values(std::vector<Scalar> &values, std::vector<double> x);

假设我有一些其他类(我不想模板)和一个调用其中一个的成员函数。

// populate double x and std::vector<double> xs
auto value = functionPtr->value(x);
std::vector<auto> values;
functionPtr->values(values, xs);
// do something with value and values

其中functionPtr的类型为std::shared_ptr<AbstractFunction>。 我可以看到auto为第一个案例工作,但我不相信我可以构建一个auto的向量来填充第二个案例。这是否必须使调用类成为模板?有人可以推荐另一种策略来减少模板的扩散吗?

1 个答案:

答案 0 :(得分:1)

我认为你假设第一个用例会起作用已经错了。如果您有一个抽象基类,那么value是其成员,您可以通过std::shared_ptr<AbstractFunction>value调用它不是它的成员,只有在您知道派生班&#39;类型。在第一种情况下,AbstractFunction::value方法必须具有固定的返回类型,它不能依赖于Scalar,这是派生类的模板参数。

那说:根据我的经验,这两个概念往往不能很好地融合。您要么想要使用完整界面创建抽象基类,要么想要模板。在后一种情况下,拥有抽象基类通常没有必要/没有好处。然后,使用您的模板的代码也可以使用模板。

可能对您有帮助的是&#34; export&#34;来自Function的模板参数,即

template<typename T>
class Function
{
public:
    using value_type = T;
    value_type value() const;
    // ...
};

在代码的其他部分,如果您不想直接写出(并限制自己)T,请使用一个模板Function,其行为类似于Function 1}}:

template<typename T>
void something( const std::shared_ptr<T>& functionPtr )
{
   // ignoring where x comes from...
   using V = typename T::value_type;
   V value = functionPtr->value(x);
   std::vector<V> values;
   functionPtr->values(values, xs);
}

请注意,这只是一个选项,我不知道它是否是您用例的最佳选择。

相关问题