Разработка hiearchical классов с функцией шаблона

Я пишу класс Base которая имеет функцию-член, принимающую параметр шаблона:

class Base {
  template<class T>
  void func(const T& t) { ... }
};

Там есть класс Derived который концептуально наследует природу Base и имеет ту же функцию func с разной реализацией.

Сначала я подумал о выводе Derived от Base и сделать func виртуальный, но я не могу, потому что это шаблон.

Я также подумал о CRTP, но это вариант, потому что экземпляры должны быть в состоянии поместить в контейнер и быть доступными, не зная точных их типов:

std::vector<Base*> v = ...;
v[0]->func(...);
v[1]->func(...);

Перегрузка для возможных типов T тоже не вариант.

Как лучше всего решить эту ситуацию?

И помимо темы, вы бы порекомендовали ссылки (желательно книги) для такого рода проблем?

2 ответа

Это не легко сделать с помощью C++. Это связано с тем, что называется "полиморфизмом первого класса", что означает, что было бы легко, если бы значения в C++ могли иметь полиморфные типы. Это не вариант.

Если вы будете в порядке с общим решением (это означает, что код f должно быть одинаковым для всех T), вы можете сделать это, но это будет трудоемкой задачей.

По сути, вы захотите заменить свой const T &t параметр с параметром, тип которого не будет универсальным, но будет захватывать "внутри" все поведение f нуждается от t с всех возможных типов.

Для примера скажем T должен быть функтором, который f звонки с int аргумент. В этом случае вы измените объявление на

  virtual void func(const std::function<void(int)>& t) { ... }

и виртуальные функции начнут работать. Тем не менее, это означает, что интерфейс T s нужно исправить до того, как вы начнете реализовывать его в производных классах (то есть, если вы передумаете и захотите вызвать t с аргументом типа ostream, не повезло тебе).

Однако создание таких полиморфных оболочек варьируется от простого (как boost::any, boost::function) трудно или даже невозможно (any_iterator). Это очень зависит от того, что вы хотите сделать.

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

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

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

Другие вопросы по тегам