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

Вот мой лучший выстрел для резюме вопроса:

Когда несколько отдельных классов наследуют каждый из нескольких отдельных баз
классы, как мне использовать механизм наследования, чтобы написать функцию
что принимает объекты из нескольких этих базовых классов в качестве параметров?

Но лучше объяснить на примере.

У меня есть библиотека, которая предоставляет следующие классы в своем API:

class A{..};

class B{..};

Эти классы предназначены для того, чтобы скрыть сложность шаблонов от используемого приложения. Реализация включает в себя шаблоны:

template <Type1>
class AImpl: public A{..};

template <Type2>
class BImpl: public B{..};

Проблема в том, что мне нужна функция вроде:

void foo(A insta,B instb);

Механизм наследования, кажется, не очень мне здесь помогает, так как если функция находится внутри AImpl для него нет возможности автоматически выбрать правильное Type2 за BImpl (без списка динамических приведений).

Мое лучшее решение на данный момент — дважды шаблонировать один из классов:

template <Type1,Type2>
class BImpl: public B{
void foo(A insta);
};

Но этот подход, похоже, не распространяется на ситуацию, когда было бы полезно объединить A а также B с несколькими произвольно заданными экземплярами (для этого требуется динамическое приведение, которое работало бы только в том случае, если был уверен, что параметр insta был на самом деле AImpl<Type2> — или вышеупомянутый список приведений).

Не добавляя сложности пользователю A а также BМожно ли сделать то, что я пытаюсь сделать здесь, или есть более идиоматический подход?

Спасибо всем.

редактировать

Это может быть неуместно в свете ответа Барта ван Ингена Шенау, но в ответ на запросы Наваза и Энди Провла я сформулировал следующий файл примера. Для этого нужна библиотека PCL, но это рабочий код (хотя это урезанный пример того, чего я пытаюсь достичь).

Спасибо всем за ваш вклад.

Класс Features аналогично A выше и Keypoint в B выше. Я добавил тег PCL к вопросу тоже.

#include <pcl/features/fpfh.h> //gives pcl::PointCloud, pcl::FPFHSignature33, etc.

//interface
class Keypoints{
public:
virtual unsigned int size();
//more virtual methods here
};
class Features{
public:
virtual unsigned int size();
//more virtual methods here
};

//implementation
template<typename KeypointType>
class KeypointsImpl:public Keypoints{
public:
typename pcl::PointCloud<KeypointType>::Ptr keypoints_;
virtual unsigned int size(){ return keypoints_->size();}
//more implementations of virtual methods here
};

template<typename FeatureType>
class FeaturesImpl:public Features{
public:
typename pcl::PointCloud<FeatureType>::Ptr features_;
virtual unsigned int size(){ return features_->size();}
//more implementations of virtual methods here
};

//void removeBadFeatures(Keypoints k,Features f); //<-- would like to have this too

int
main (int argc, char ** argv)
{
//Class construction could be done anywhere.
Features *f = new FeaturesImpl<pcl::FPFHSignature33>();
Keypoints *k = new KeypointsImpl<pcl::PointXYZ>();

int a = f->size();
int b = k->size();
//removeBadFeatures(k,f); //will alter f and k in concert
}

-4

Решение

Если я вас правильно понимаю, вы пишете библиотеку, которая использует несколько независимых шаблонов (Aimpl, Bimpl, так далее.). Чтобы скрыть этот факт от пользователей библиотеки, вы выставляете только не шаблонные базовые классы этих шаблонов (A, B, так далее.).
Теперь у вас есть функция foo он должен работать с двумя шаблонными типами, передаваемыми как ссылки на их базовые классы, и вы сталкиваетесь с проблемой, которую вы не можете (легко) определить, к каким шаблонам относятся параметры.

Есть только несколько вариантов решения этой дилеммы:

  1. Написать foo полностью с точки зрения операций, которые работают с базовыми классами (поскольку это вся информация, которая foo есть).
  2. Серьезно переосмыслите дизайн своей библиотеки с точки зрения использования наследования, чтобы скрыть шаблоны.
  3. Напишите бесконечный список dynamic_casts, чтобы определить, с каким производным классом вы работаете. (Лучше всего избегать этой опции, если это возможно, потому что это настоящий кошмар.)
1

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

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

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