Ну, ты не можешь. Каждый отдельный фактический параметр шаблона создает совершенно новый класс, который не имеет * отношения наследования отношений с любым другим классом, с различным действительным аргументом, сделанным из этого шаблона.
Нет отношений. Ну, за исключением того, что каждый из них предоставляет один и тот же интерфейс, так что внутри шаблона вы можете обрабатывать то же самое.
Но ни статические, ни динамические типы не имеют никакого отношения.
Позвольте мне вернуться сюда и объяснить.
Когда я объявляю указатель на класс, например
Foo fp*;
fp имеет то, что мы называем статическим типом указателя на Foo. Если класс Bar является подклассом Foo, и я указываю fp на новый Bar:
fp = new Bar1();
тогда мы говорим, что объект, на который указывает fp, имеет динамический тип Bar.
если Bar2 также публично происходит от Foo, я могу сделать это:
fp = new Bar2();
и даже не зная, на что указывает fp, я могу вызывать виртуальные методы, объявленные в Foo, и заставить компилятор удостовериться, что метод, определенный в динамическом типе, на который он указывает, называется.
Для template< typename T > struct Baz { void doSomething(); };
Baz<int>
и Baz<float>
- два совершенно разных типов классов , без взаимосвязи.
Единственное «отношение» - это то, что я могу вызывать doSomething () для обоих, но поскольку статические типы не имеют отношения, если у меня есть Baz<int> bi*
, я не могу указать его на Baz<float>
. Даже с актерами. Компилятор не может «перевести» вызов метода Baz doSotheing в вызов метода Baz :: doSomething (). Это потому, что в нет «метода Baz», нет Baz , есть только Baz<int>s
, Baz<float>s
и Baz<whatevers>
, но нет общего родителя. Baz - это не класс, Baz - это шаблон, набор инструкций о том, как создать класс, если и только если у нас есть параметр T, связанный с фактическим типом (или константой).
Теперь есть один способ, которым я могу обращаться с этими Baz
одинаково: в шаблоне они представляют один и тот же интерфейс, и компилятор, если он знает, с каким Baz мы на самом деле имеем дело, может сделать static вызов этого метода (или статический доступ к переменной-члену).
Но шаблон - это не код, шаблон - это метакод, инструкции о том, как синтезировать класс. «Вызов» в шаблоне - это не вызов, а инструкция о том, как написать код для вызова.
Итак. Это было долго и запутанно. Вне определения шаблона нет никакой связи между ParamVector и aParamVector. Так что ваше задание не может работать.
Хорошо. Почти.
На самом деле, с частичным применением шаблонов, вы можете написать шаблонную функцию , которая дает «рецепт» того, как преобразовать Paramvector<T>
в ParamVector<U>
. Обратите внимание на T и U. Если вы можете написать код для преобразования любого типа ParamVector, независимо от фактического параметра шаблона, в любой другой тип ParamVector, вы можете упаковать его как частично примененный шаблон, и компилятор добавит эту функцию в Например, ParamVector.
Это, вероятно, включает в себя ParamVector<U>
и преобразование каждого T в ParamVector<T>
в U для вставки ParamVector<U>
. Который все еще не позволит вам присвоить ParamConsumer<T>
.
Так что, может быть, вы хотите иметь как шаблоны, так и наследование. В этом случае вы можете сделать то же самое, что все ParamVectors независимо от типа наследуются от некоторого не шаблонного класса. И тогда между ParamVectors будет связь, все они будут подклассами этого базового класса.