【发布时间】:2018-12-03 04:26:25
【问题描述】:
我有这个函数模板:
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() 以正确接受这些类。
【问题讨论】:
-
你还需要
TemplateType吗?struct C没有模板化。 -
编译器不确定是否将
args类型推断为B<A>或S<A>。 -
@r3mus_n0x 一方面我同意你的观点,另一方面编译器不应该选择最衍生的替代方案吗?
-
@navyblue 我不希望它自动执行标准中未明确指定的任何操作。我从未读过或听说过这样的模板推导规则。
-
@r3musn0x: 哦,我现在明白了……我也希望它能够推断出最派生的类。您认为编译器不需要自动推断这种情况是 C++ 标准中的错误吗?还是因为某种原因,这样的扣除与现行标准不兼容?
标签: c++ templates c++14 language-lawyer c++17