【发布时间】:2019-03-17 19:41:33
【问题描述】:
cppreference 声明如下
template <class ...T> int f(T*...); // #1
template <class T> int f(const T&); // #2
f((int*)0); // OK: selects #1
// (was ambiguous before DR1395 because deduction failed in both directions)
如果我们关注DR1395,我们会看到
如果 A 是从函数参数包转换而来的,而 P 不是参数包,则类型推导失败。否则,使用使用产生的类型 P 和 A,然后按照 17.9.2.5 [temp.deduct.type] 中的描述进行扣除。如果 P 是函数形参包,则将实参模板的每个剩余形参类型的类型 A 与函数形参包的 declarator-id 的类型 P 进行比较。每个比较推导出模板参数包中由函数参数包扩展的后续位置的模板参数。 类似地,如果 A 是从函数形参包转换而来的,则将其与形参模板的每个剩余形参类型进行比较。 如果给定类型的推导成功,则认为实参模板中的类型为至少与参数模板中的类型一样专业化。[...]
如果在考虑以上之后,函数模板 F 至少与函数模板 G 一样特化,反之亦然,并且如果 G 有一个尾随参数包,而 F 没有对应的参数,并且如果F 没有尾随参数包,则 F 比 G 更特化。
据我推断,这意味着我们应该匹配从T*... 扩展为const T& 的每个单独类型,反之亦然。在这种情况下,T* 比 const T& 更专业(来自U* 的T 成功,来自U 的T* 失败)。
但是,编译器不同意。 Clang thinks it's ambiguous 和 gcc thinks the second should be called,两者都不同于 cppreference。
正确的行为是什么?
【问题讨论】:
-
编译器在执行核心问题解决方案方面落后并不奇怪。
标签: c++ language-lawyer