У меня есть иерархия классов со следующими тремя классами:
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;
};
которая является функцией изldim-мерное локальное пространство узла в pdim-мерном пространстве.
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 является более общей, чем функция.Он всегда может отобразить локальную точку ldim-точки на pdim-точку.Например, ребро (Узел с ldim = 1) отображает интервал [0,1] в физическое пространство pdim.Вот почему каждая функция является NodeFunction .Функция NodeFunction является более общей, поскольку NodeFunction разрешено запрашивать у узла атрибуты.
Причина 2 для этой схемы: функция PNodeFunction является более общей, чем функция NodeFunction.Ровно один Узел связан с каждым PNode (не наоборот).Вот почему каждая PNodeFunction является NodeFunction .Функция PNode является более общей, поскольку она также имеет весь контекст PNode, который является частью Mesh (таким образом, он знает всех своих родителей, соседей, ...).
Сводка :Каждый 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 '
Чтобы учесть производительность, обратите внимание, что в программе создано несколько функций, но их оператор () вызывается много раз.
Варианты
Я подумал о нескольких способах реализации этого (в настоящее время я реализовал Вариант 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>;
Это применяется как для наследования Function от NodeFunction, так и NodeFunction от PNodeFunction.Как NodeFunction наследует примерно O(pdim^2)
раз от PNodeFunction, как это масштабируется?Неужели эта огромная виртуальная таблица плоха?
Примечание : Фактически каждая функция также должна наследоваться от 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
Каков ваш предпочтительный способ реализации этого?