Предположим следующую ситуацию:Как ограничить параметры шаблона потомком, который является специализацией шаблонного интерфейса?
- Там является шаблонный интерфейс, определяющий набор операций на различных типах данных.
- Этот интерфейс реализован различными специализированными классами, определяющими операции для фактических типов данных.
- Существует некоторый управляющий класс, который должен работать экземпляры классов, как это определено в 2
Упрощенный пример кода может выглядеть следующим образом:
#include <iostream>
#include <type_traits>
template <typename R, typename S>
class ICanDoIt
{
public:
virtual void doStuff() = 0;
protected:
ICanDoIt<R, S>(R rA, S sA) : r(rA), s(sA) {};
R r;
S s;
};
class DoesIt : public ICanDoIt<int, double>
{
public:
DoesIt(int iA, double dA) : ICanDoIt(iA, dA) {};
virtual void doStuff()
{ std::cout << "r * s = " << r * s << " done." << std::endl; }
};
template <typename T>
class NeedsSomeoneWhoCanDoIt
{
static_assert(std::is_base_of<ICanDoIt<R, S>, T>::value,
"T needs to be able to do it.");
public:
NeedsSomeoneWhoCanDoIt(const T& doesItA) : doesIt(doesItA) {};
void getItDone() { doesIt.doStuff(); };
private:
T doesIt;
};
int main()
{
DoesIt doesIt(5, 2.2);
NeedsSomeoneWhoCanDoIt<DoesIt> needsIt(doesIt);
needsIt.getItDone();
}
Если вы untemplate интерфейс «ICanDoIt» код будет работать. Но static_assert для шаблонной версии не сработает, потому что аргументы шаблона ICanDoIt обернуты и скрыты специализацией, выполняемой в декалировании DoIt.
Как можно ограничить управляющие классы (NeedsSomeoneWhoCanDoIt) параметры шаблона «T», чтобы любого специализации ICanDoIt, независимо от того, какого типа было выбрано для R, S во время специализации ICanDoIt?
Идеальное решение, работает как очарование. – norritt
@norritt: Несмотря на то, что он работает со мной, ваш нынешний дизайн по-прежнему выглядит как странная химера полиморфизма времени исполнения и чрезмерно ограничительное воплощение понятий. –
Его вид результат того, что, похоже, нет способа управлять шаблонами экземпляров класса с разными аргументами шаблона в одном контейнере, за исключением использования Boost (boost :: any). Это часть моего обходного пути с использованием STL означает, что я не совсем удовлетворен сам, но это лучшее, что я придумал. Листинг типа C# в стиле исполнения приведет к тому, что все эти проблемы исчезнут;) – norritt