Согласно https://gcc.gnu.org/projects/cxx-status.html, версия 7 g++, используемая с флагом -std=c++1z, поддерживает вывод аргументов шаблона для шаблонов классов.
Я ожидаю компиляции следующего кода, тем более что Base является абстрактным классом, поэтому:
1. компилятор знает, что экземпляр Base не может быть создан;
2. указатель на базу pt_base указывает на четко определенный экземпляр (т.е. Derived<int>{42}), где тип (int) является явным.
template<typename ValueType>
class Base {
public:
virtual ValueType getValue() = 0;
};
template<typename ValueType>
class Derived : public Base<ValueType>{
public:
Derived(ValueType argt){ value = argt; }
virtual ValueType getValue(){ return value; }
ValueType value;
};
int main(){
Base *pt_base = new(Derived<int>{42}); // *ERROR*
delete pt_base;
}
Тем не менее, он не компилируется. G++ жалуется, что "за типом заполнителя шаблона 'Base' должен следовать простой идентификатор-декларатора"; если я правильно понимаю, он не выводит аргумент шаблона.
Жаль, потому что я хотел бы динамически решать, на какой производный класс pt_base указывает (может быть объект из класса Derived<someType> или из класса Derived2<someType2>). Таким образом, массив или vector<Base *> могут хранить указатели на объекты различных производных классов.
GCC имеет только экспериментальную поддержку для C++17, и у меня нет доступа другому компилятору, поэтому, хотя я получаю ошибку компиляции, я не уверен, что мой код неверен. Как вы думаете?
И как мы можем динамически решить, что pt_base указывает на объект либо из Derived<someType>, либо из Derived2<someType2> (чтобы можно было использовать полиморфизм)?
*вBase *pt_baseне разрешено.*pt_baseявляется декларатором, но не идентификатором-декларатором (например, недекорированным идентификатором). Однако я не могу найти это правило нигде в N4687. - person aschepler   schedule 07.09.2017Base, компилятор решит, действительно ли это означаетBase<someType>или что-то еще.Baseне является типом. Таким образом, у вас не может быть ни одной переменной, указывающей наDerived<someType>илиDerived<someType2>во время выполнения, если только они оба не наследуют какой-то общий тип. Вам может понадобитьсяstd::anyилиstd::variantдля возвращаемого типа егоgetValue(). - person aschepler   schedule 07.09.2017vector<Base*>был допустимым, стирание типа поддерживалось бы языком напрямую... - person Walter   schedule 07.09.2017Baseне может принимать указатель. Но при строгом чтении я думаю, чтоstd::vector&& v(1,1);может быть разрешено. Мне кажется Дефект. - person aschepler   schedule 07.09.2017