模板上下文中的"模糊基类"错误

Vio*_*ffe 13 c++ templates language-lawyer c++14 c++17

我有这个功能模板:

template <class TemplateArgument, template<class> class TemplateType>
TemplateArgument f(const TemplateType<TemplateArgument>& arg)
{
    return TemplateArgument();
}
Run Code Online (Sandbox Code Playgroud)

如果这样使用,它无法编译:

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;
}
Run Code Online (Sandbox Code Playgroud)

并且错误消息是:

<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());

          ^
Run Code Online (Sandbox Code Playgroud)

适用于GCC(任何版本)和clang(任何版本).MSVC不会发生这种情况.现场演示:https://godbolt.org/g/eWxeHJ

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

请注意,我不能编辑A,B,C,S类和它们之间的相互关系,我只能编辑我的功能f()正确地接受这些类.

r3m*_*n0x 9

编译器不确定是否将args类型推导为B<A>S<A>.我不确定这个特定情况,但已知MSVC违反了标准,特别是在模板方面.

至于你的功能,你需要通过显式地转换到适当的基础来解决这种歧义:

f((const B<A> &)C());
Run Code Online (Sandbox Code Playgroud)

或明确指定模板参数:

f<A, B>(C());
Run Code Online (Sandbox Code Playgroud)

通常,只要语言中存在任何歧义,编译器就不会自动解决它,因为它只是对用户意图究竟是什么的推测,在某些情况下可能是正确的,而在其他情况下则完全错误.

  • @VioletGiraffe,第二个参数是模板模板参数,因此它应该是`f <A,B>(C())`,应该用非实例化的模板名称替换. (3认同)