模板上下文中的“歧义基类”错误

时间:2018-06-24 10:48:36

标签: c++ templates c++14 language-lawyer c++17

我有此功能模板:

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

为什么会出现此错误?我看不到任何歧义,“歧义基类”错误通常发生在多重继承情况下,不是吗? 如何使我的代码编译(正确推断模板参数)?

请注意,我无法编辑ABCS类及其相互之间的关系,我只能编辑函数{{1} },以正确接受这些类。

1 个答案:

答案 0 :(得分:9)

编译器不确定是否将arg的类型推断为B<A>S<A>。我不确定这种情况,但已知MSVC违反了该标准,尤其是在模板方面。

对于您的功能,您需要自己通过显式转换为适当的基数来解决这种歧义:

f((const B<A> &)C());

或通过明确指定模板参数:

f<A, B>(C());

通常,只要该语言存在歧义,编译器就不会自动解决它,因为这只是在猜测用户的确切意图,在某些情况下可能是正确的,而在另一些情况下则完全是错误的。