我有一个包含以下三个类的类层次结构:

template<int pdim >
class Function
{
   virtual double operator()( const Point<pdim>& x) const = 0;
};

这是pdim维空间中的函数,返回 double 值。
template<int pdim, int ldim >
class NodeFunction
{
   virtual double operator()( const Node<pdim,ldim>& pnode, const Point<ldim>& xLoc) const = 0;
};

它是pdim维空间中节点的ldim维局部空间的函数。
template<int pdim, int ldim, int meshdim >
class PNodeFunction
{
   virtual double operator()( const PNode<pdim,ldim,meshdim>& pnode, const Point<ldim>& xLoc) const = 0;
};

此设计的原因1:NodeFunction比Function更通用。它始终可以将本地ldim点映射到pdim点。例如,边缘(具有ldim = 1的节点)将间隔[0,1]映射到pdim维物理空间。这就是每个函数都是NodeFunction的原因。 NodeFunction更通用,因为允许NodeFunction向Node查询属性。

此设计的原因2:PNodeFunction比NodeFunction更通用。每个PNode恰好关联一个节点(反之亦然)。这就是每个PNodeFunction都是NodeFunction的原因。 PNodeFunction更通用,因为它还具有属于Mesh的PNode的所有上下文(因此它知道其所有父级,邻居...)。

摘要:每个Function<pdim>都是NodeFunction<pdim, ldim>的任何参数的ldim。每个NodeFunction<pdim, ldim>都是NodeFunction<pdim, ldim, meshdim>的任何参数的meshdim

问题:用C++表示的最佳方法是什么,这样我就可以使用Function代替NodeFunction / PNodeFunction,从而使代码快速(它是一种高性能的计算代码),从而使该代码适用于

模板参数不是完全独立的,而是彼此依赖的:
-pdim=1,2,3(主要关注),但如果它也适用于pdim的值(最大为7),那就很好了。
-'ldim = 0,1,...,pdim'
-'meshdim = ldim,ldim + 1,...,pdim'

要考虑性能,请注意,在程序中创建了一些函数,但是它们的operator()被多次调用。

变体

我考虑了几种实现此方法的方法(我目前实现了变体1)。我在这里写下来,以便您可以告诉我这些方法的优点和缺点。

变体1

通过助手模板A<dim> inherits from B<dim,dim2>实现上述继承Arec<dim,dim2>。在伪代码中,这是
class A<dim> : public Arec<dim,dim>;
class Arec<dim,dim2> : public Arec<dim,dim2-1>, public B<dim,dim2>;
class Arec<dim,0> : public B<dim,dim2>;

这适用于继承NodeFunction的Function和PNodeFunction的NodeFunction。由于NodeFunction从PNodeFunction继承了O(pdim^2)的大致时间,它如何扩展?这个巨大的虚拟表不好吗?

注意:实际上每个函数也应该继承自VerboseObject,这使我可以将有关函数的调试信息打印到例如std::cout。我实际上是通过从PNodeFunction继承VerboseObject来实现的。这将如何影响性能?这应该增加构造函数和打印调试信息的时间,而不是operator()的时间,对吗?

变体2

不要在C++中表达继承,例如A<dim>不会从B<dim,dim2> bur继承,而是有一个将两者转换的函数
class AHolder<dim,dim2> : public B<dim, dim> {

}

std::shared_pointer< AHolder<dim,dim2> > interpretAasB( std::shared_pointer< AHolder<dim> >)
 [...]

缺点是我不能再使用Function<dim>代替NodeFunction<dim>PNodeFunction<dim>

变体3

您首选的实现方式是什么?

最佳答案

我不太了解你的问题。那可能是因为我缺乏对问题域的具体了解。
无论如何,似乎您想生成一个类的层次结构,在底部是Function(派生最多的类),在顶部是PNodeFunction(派生最少的类)。
为此,我只能推荐Alexandrescu的Modern C++设计书,尤其是有关层次生成器的章节。
本书名为Loki,有一个开源库。
Here's the part that might interest you.

采用通用元编程方法可能是最困难的,但我认为,一旦设置,它将带来易用性,并且与虚拟继承相比,可能会提高性能(始终由探查器验证)。

无论如何,我强烈建议不要从Verbose对象继承进行日志记录,而要拥有单独的单例日志记录类。
这样,您就不需要在类层次结构中额外的空间来存储日志记录对象。
您只能从Verbose对象继承最少的派生类,但您的函数类不是日志对象;他们使用了一个日志记录对象(我在这里可能有点学究)。另一个问题是,如果您从该基类继承多次,则最终将获得日志记录对象的多个副本,并且必须使用虚拟继承来解决该问题。

09-06 19:43