为什么 C++ 模板接受数组并不比一个接受指针 (bis) 更专业?
Why C++ template accepting array is not more specialized than one accepting pointer (bis)?
参考 this question,它确实具有相同的标题,但我在标准中找到了答案。我继续挖掘这个主题并最终找到了一个示例代码,这个答案不适用。
让我们考虑这段代码:
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)
}
根据 [temp.func.order] and [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
}
所以根据这个解释,模板 II 应该更专业。为什么不是这样?
作为n.m。在评论中指出,原因是无法从类型 char (&buf)[invented_N]
.
推导出类型 T*
在is_template_II_more_specialized
中,根据[temp.deduct.call]/2.1:
应用额外的数组到指针转换
If P is not a reference type:
If A is an array type, the pointer type produced by the array-to-pointer standard conversion is used in place of A for type deduction; otherwise,
...
此规则仅适用于从函数调用中推导模板参数。对于在部分排序期间推导模板参数,没有应用此类转换。
参考 this question,它确实具有相同的标题,但我在标准中找到了答案。我继续挖掘这个主题并最终找到了一个示例代码,这个答案不适用。
让我们考虑这段代码:
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)
}
根据 [temp.func.order] and [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
}
所以根据这个解释,模板 II 应该更专业。为什么不是这样?
作为n.m。在评论中指出,原因是无法从类型 char (&buf)[invented_N]
.
T*
在is_template_II_more_specialized
中,根据[temp.deduct.call]/2.1:
If P is not a reference type:
If A is an array type, the pointer type produced by the array-to-pointer standard conversion is used in place of A for type deduction; otherwise,
...
此规则仅适用于从函数调用中推导模板参数。对于在部分排序期间推导模板参数,没有应用此类转换。