Ошибка "Неопределенный базовый класс" в контексте шаблона
У меня есть этот шаблон функции:
template <class TemplateArgument, template<class> class TemplateType>
TemplateArgument f(const TemplateType<TemplateArgument>& arg)
{
return TemplateArgument();
}
При использовании подобным образом он не компилируется:
struct A {};
template <typename T> struct S {};
template <typename T> struct B : public S<T> {};
struct C : public B<A> {};
int main()
{
f(C());
return 0;
}
И сообщение об ошибке:
<source>: In function 'int main()':
<source>:15:10: error: no matching function for call to 'f(C)'
f(C());
^
<source>:2:18: note: candidate: template<class TemplateArgument, template<class> class TemplateType> TemplateArgument f(const TemplateType<TemplateArgument>&)
TemplateArgument f(const TemplateType<TemplateArgument>& arg)
^
<source>:2:18: note: template argument deduction/substitution failed:
<source>:15:10: note: 'const TemplateType<TemplateArgument>' is an ambiguous base class of 'C'
f(C());
^
Происходит с GCC (любая версия) и clang (любая версия). Не происходит с MSVC. Демо-версия: https://godbolt.org/g/eWxeHJ
Почему эта ошибка возникает? Я не вижу никакой двусмысленности, ошибка "двусмысленного базового класса" обычно возникает в нескольких ситуациях наследования, не так ли? Как я могу скомпилировать свой код (правильно вывести аргументы шаблона)?
Обратите внимание, что я не могу редактировать классы A
, B
, C
, S
и их отношение друг к другу, я могу только изменить свою функцию f()
чтобы правильно принять эти классы.
Ответы
Ответ 1
Компилятор не уверен, следует ли выводить тип arg
как B<A>
или S<A>
. Я не уверен в этом конкретном случае, но MSVC, как известно, нарушает стандарт, особенно когда дело касается шаблонов.
Что касается вашей функции, вам нужно решить эту двусмысленность самостоятельно, явно наведя ее на соответствующую базу:
f((const B<A> &)C());
или указав параметры шаблона явно:
f<A, B>(C());
Как правило, всякий раз, когда есть какая-либо двусмысленность в языке, он никогда автоматически не разрешается компилятором, потому что это просто предположение о том, что именно сделал пользователь, что может быть правильным в некоторых случаях и совершенно неверным в других.