【问题标题】:Why C++ template accepting array is not more specialized than one accepting pointer (bis)?为什么 C++ 模板接受数组并不比一个接受指针 (bis) 更专业?
【发布时间】:2018-07-03 22:07:49
【问题描述】:

参考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][temp.deduct.partial] 中的偏序规则,如果通过执行这段代码:

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应该是更专业的。为什么不是这样?

【问题讨论】:

  • 非正式的 C++ 文档来源(cppreference、msvc 文档等)表示在执行部分排序的推导时不考虑隐式转换。我自己找不到任何相关的标准。 (我最初在链接的问题下对此发表了评论,然后将其删除,因为它在那里似乎不相关;但它可能与此处相关)。
  • @n.m.所以调用func1(buf) 也不会编译,所以这两个模板都不会更专业。这是你的主意吗?如果您发布它,那将是我会接受的答案。
  • 这些是函数模板,AFAIK 没有函数模板的部分特化之类的东西;相反,在函数调用时,两个候选模板中的每一个都是完全特化的(如果可能的话),产生函数名称的候选 重载,然后重载决策规则是应用,好像根本没有涉及任何模板。这会将问题简化为“为什么void func(char (&amp;buf)[42])void func(char *buf) 是一个模棱两可的重载对?”我不知道答案。
  • @zwol 你的权利,然后选择最佳可行函数的过程继续进行:这两个函数调用的转换顺序排名相同,然后应用以下规则[over.match.best]F1和 F2 是函数模板特化,根据 [temp.func.order] 中描述的偏序规则,F1 的函数模板比​​ F2 的模板更特化,
  • @Oliv 是的,这正是这个想法,但我需要在实际的标准文本中找到它才能绝对确定,

标签: c++ templates language-lawyer partial-ordering


【解决方案1】:

作为 n.m.评论中指出,原因是T*类型不能从char (&amp;buf)[invented_N]类型推导出来。

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

如果 P 不是引用类型:

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

  • ...

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

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

【讨论】:

  • 这确实是 n.m.在其评论中得出结论。感谢您编写它。
  • @Oliv 抱歉,我没有注意到评论...现在我添加“正如 n.m. 指出的那样”,因为评论早于我的回答。
猜你喜欢
  • 2018-07-02
  • 1970-01-01
  • 2015-12-05
  • 2020-06-22
  • 2021-10-29
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多