Виртуальный шаблон функции обходной путь

Я наткнулся на проблему, которую я (и никто из моих более знающих коллег) не знаю, как ее решить (обойти). В конце концов, проблема заключается в том, что невозможно создать функцию виртуального шаблона. Я тщательно обыскал сеть, нашел несколько способов борьбы с ней, но, похоже, ни один из них не применим в моем случае.

Я не знаю, как описать эту ситуацию вкратце, но я приложу все усилия и надеюсь, что это имеет смысл.

Проблема заключается в обработке двух кривых, каждая из которых состоит из одного или нескольких сегментов одинаковых или разных типов кривых. Поэтому я начал с создания интерфейса для сегмента кривой с классом шаблона кривой, с которым он будет взаимодействовать (например, функции того же типа, что и пересечения между двумя различными сегментами кривой):

template<class curve> class curve_segment { // some methods here }

пользователь может затем реализовать несколько типов кривых и соответствующие функции в зависимости от того, с какими кривыми он будет взаимодействовать. Например, circle а также lineгде оба могут взаимодействовать с обоими:

class line :  public curve_segment<line>, public curve_segment<circle> { //... }
class circle :  public curve_segment<line>, public curve_segment<circle> { //... }

После этого у меня есть класс cell, который зависит от двух сегментов кривой и базового класса cell_base который инкапсулирует это:

template<class curve1, class curve2> class cell : public cell_base {
cell_base* up; cell_base* down;

curve_segment<curve1>* segment_x;
curve_segment<curve2>* segment_y;

// some methods that depend on both curves
}

В конце концов, существует двумерная сетка m * n таких ячеек, где две кривые состоят из m и n curve_segments возможно разных типов, и удерживается вместе двумя указателями в каждой ячейке.

Проблема начинает показывать, когда новый сегмент кривой будет добавлен к одной из двух кривых. Очевидное решение было бы добавить

template<class curve> virtual void add_curve_x(curve_segment<curve> seg) =0;

к cell_base класс, где реализация в cell может извлечь соответствующий сегмент другой кривой и добавить к нему новую ячейку. Например, если кривые a а также b где a представляет ось х в сетке, и мы должны были добавить еще один сегмент кривой к кривой aмы могли бы найти правую руку в большинстве ячеек сетки, извлечь кривую на оси у каждой такой ячейки, и из этого и вновь предоставленного сегмента создать новую ячейку, которая добавится к ее правому краю.

Стирание типа не сработает, так как нам нужно знать тип вновь добавленного сегмента в точке cell создание (нам нужно предоставить типы обоих сегментов в качестве параметров шаблона для cell учебный класс).

Перемещение шаблона в cell_base класс также не будет работать, так как это будет означать, что во время каждого cell распределение я должен был бы знать тип следующего curve_segment,

Это можно обойти?

редактировать:
Как и предполагалось, добавление add_curve_x метод:

template<class curve1, class curve2>
template<class curve>
cell<curve1, curve>* cell<curve1, curve2>::add_curve_x(curve_segment<curve1>* seg) {
return new cell<curve1, curve>(seg, (curve_segment<curve>*)(this->segment_y));
}

В этом случае seg должен быть типа curve, который должен реализовать curve_segment<curve1>, segment_y также должен реализовать curve_segment<curve>,

редактировать 2: объяснение, почему актеры там

фильм

Возьмите случай с не полужирным прямоугольником. В этих ситуациях есть две кривые, кривая a с 2 сегментами и кривой b с 3 сегментами. учебный класс line должен реализовать curve_segment<line> так же как curve_segment<circle>, и круг должен реализовать и то и другое. Теперь давайте добавим еще один сегмент кривой Безье к кривой a, учебный класс bezier должен реализовать curve_segment<line> а также curve_segment<circle>, а также line а также circle должны реализовать curve_segment<bezier>,

Давайте посмотрим, как мы создаем середину жирной тройки cells, Мы бы позвонили

add_curve_x<bezier>(new bezier(...));

на объекте типа ячейки cell<circle, circle>,

Аргумент seg будет новым bezier объект (который может быть приведен к curve_segment<circle>), и это также то, что curve тип есть, и segment_y должен быть приведен к curve_segment<bezier>, поскольку это тип кривой, с которой он взаимодействует во вновь созданной ячейке.

1

Решение

добавлять curve_segment_base:

class curve_segment_base {
// for double dispatching here:
virtual cell_base* add_curve_x(cell_base* cell) = 0;
};

template<class curve>
class curve_segment : public virtual curve_segment_base {
// some specific methods here
// for double dispatching here:
virtual cell_base* add_curve_x(cell_base* cell)
{
// this has to be moved to cpp file due to dependency from cell_base
return cell->add_curve_x(this); // now the correct method from cell is called
}
};

Таким образом, вы можете добавить этот метод как виртуальный к своей cell_base

class cell_base {
virtual cell_base* add_curve_x(curve_segment_base* seg) = 0;

// methods necessary for double dispatching here:
virtual cell_base* add_curve_x(curve_segment<line>* seg) = 0;
virtual cell_base* add_curve_x(curve_segment<circle>* seg) = 0;
...
};

Итак, ваш метод будет выглядеть так, с двойной диспетчеризацией здесь:

template<class curve1, class curve2>
virtual cell_base* cell<curve1, curve2>::add_curve_x(curve_segment_base* seg) {
return seg->add_curve_x(this);
}

И вам придется реализовать все реальные методы реализации для всех сегментов:

template<class curve1, class curve2>
virtual cell_base* cell<curve1, curve2>::add_curve_x(curve_segment<line>* seg) {
return new cell<curve1, line>(...);
}
template<class curve1, class curve2>
virtual cell_base* cell<curve1, curve2>::add_curve_x(curve_segment<circle>* seg) {
return new cell<curve1, circle>(...);
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]