Oli*_*liv 7 c++ templates partial-ordering language-lawyer
在提到这个问题时,该问题确实具有相同的标题,但我在标准中找到了答案.我继续挖掘这个主题,最后找出一个不适用这个答案的示例代码.
让我们考虑一下这段代码:
template<class T> void func(T* buf); //template I
template<size_t N> void func(char (&buf) [N]); //template II
void g(char (&buf)[3])
{
func(buf) //Error: ambiguous function call (Clang, GCC, ICC, MSVC)
}
Run Code Online (Sandbox Code Playgroud)
根据[temp.func.order]和[temp.deduct.partial]中的部分排序规则,如果通过执行这段代码解释了这个规则,模板II应该比模板I更专业:
template <class T> void func1(T* buf) {}
template <std::size_t N> void func2(char (&buf)[N]) {}
struct invented_T{};
constexpr std::size_t invented_N=42;
void is_template_I_more_specialized(invented_T* buf)
{
func2(buf);
//DO NOT COMPILE
// => template I is not more specialized than func2
}
void is_template_II_more_specialized(char (&buf)[invented_N])
{
func1(buf);
//DO COMPILE
// => template II is more specialized than func1
}
Run Code Online (Sandbox Code Playgroud)
因此,根据这种解释,模板II应该更加专业化.为什么不是这样?
正如 nm 在评论中指出的那样,原因是这种类型T*无法从 type 推导出来char (&buf)[invented_N]。
在 中is_template_II_more_specialized,根据[temp.deduct.call]/2.1应用了额外的数组到指针转换应用额外的数组到指针转换:
如果 P 不是引用类型:
如果A是数组类型,则使用数组到指针标准转换产生的指针类型代替A进行类型推导;否则,
...
此规则仅适用于从函数调用中推导模板参数。用于在部分排序期间推导模板参数推导模板参数,没有应用此类转换。
[temp.deduct.partial]/ 5 , 6 , 7中描述了可以在部分排序期间应用的转换。