Разработка 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, а затем использовать этот список типов для генерации методов... но это будет ужасно кодировать и поддерживать.
Я рекомендую вам указать действительные требования к проблеме (а не требования предложенного вами решения), и люди смогут предоставить альтернативные подходы.