7

关于这个问题,它确实具有相同的标题,但我在标准中找到了答案。我继续挖掘这个主题,最后找到了一个不适用这个答案的示例代码。

让我们考虑这段代码:

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][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
  }

所以按照这个解释,模板二应该更专业。为什么不是这样?

4

1 回答 1

3

正如 nm 在评论中指出的那样,原因是 typeT*不能从 type 推导出来char (&buf)[invented_N]

is_template_II_more_specialized中,根据[temp.deduct.call]/2.1应用了额外的数组到指针的转换:

如果 P 不是引用类型:

  • 如果A是数组类型,则使用数组到指针标准转换产生的指针类型代替A进行类型推导;否则,

  • ...

此规则仅适用于从函数调用推导出模板参数。对于在部分排序期间推导模板参数,没有应用这样的转换。

[temp.deduct.partial]/ 5 , 6 , 7中描述了可以在部分排序期间应用的转换。

于 2018-01-25T05:42:07.883 回答