首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >添加重载更改,选择哪些重载?

添加重载更改,选择哪些重载?
EN

Stack Overflow用户
提问于 2018-09-20 15:49:51
回答 1查看 173关注 0票数 12

我试图理解重载选择规则是如何导致以下(不直观的)行为的。当我有以下职能时:

代码语言:javascript
复制
#include <iostream>

// Overload 1
template<class T>
void write(T data)
{
  std::cout << "Called write(T data)" << std::endl;
}

// Overload 2
template<class T, class ...U>
void write(T&& obj, U&&... objs)
{
  std::cout << "Called write(T&& obj, U&&... objs)" << std::endl;
}

int main(int, char**)
{
  int j = 0;
  write(j);
  return 0;
}

选择void write(T data)过载(重载1)。我认为这对我来说是有道理的:过载选择的候选人是void write<T>(T) T = intvoid write<T,U>(T&) T = int, U = <>write(T)write(T&)都是同样专门化的,但是重载2有一个空的参数包,所以选择重载1。但是,如果我添加第三个重载:

代码语言:javascript
复制
#include <iostream>

// Overload 0
void write(const int& data)
{
  std::cout << "Called write(const int& data)" << std::endl;
}

// Overload 1
template<class T>
void write(T data)
{
  std::cout << "Called write(T data)" << std::endl;
}

// Overload 2
template<class T, class ...U>
void write(T&& obj, U&&... objs)
{
  std::cout << "Called write(T&& obj, U&&... objs)" << std::endl;
}

int main(int, char**)
{
  int j = 0;
  write(j);
  return 0;
}

然后突然之间,void write(T&& obj, U&&... objs) (重载2)被称为。为什么添加一个没有被选择的重载会改变哪些重载实际上会被选中?

如果唯一的候选者是void write<T,U>(T&) T = int, U = <>void write(const int&),我理解为什么会选择void write<T,U>(T&),那么添加额外的重载可能会阻止void write(T data)参与过载选择?如果是的话,为什么?

因为这似乎是编译器的特定行为,所以在gcc 7.3.0上观察到了这一点。

一些更有趣的行为:如果对函数进行重新排序,使得新的重载被放置在原来的两个(即重载1,然后重载0,然后重载2)之间,那么gcc用call of overloaded ‘write(int&)’ is ambiguous拒绝它。如果对函数进行重新排序,使新的重载成为最后一个(即重载1,然后重载2,然后重载0),则选择write(const int& data)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-20 18:12:18

我想这是GCC的一个错误:

超载情况如下:

  • 过载0:write(const int&)
  • 过载1:write(T) [T=int] -> write(int)
  • 过载2:write(T&&,U&&...) [T=int&,U=[]] -> write(int&)

重载0比重载1更匹配,因为重载0不是模板函数的专门化。

重载1比重载2更匹配,因为重载1是比重载2更专业的函数模板。

重载2比重载0更匹配,因为重载2 int&的参数类型的cv限定符是重载0:const int&的子集。

因此,正如Clang报告的那样,这一呼吁是模棱两可的。

为了简化,最好的可行函数是在这里按4个步骤计算,当比较两个函数时:

  1. 检查哪个是最佳的转换序列(这里的所有转换都是身份转换),如果转换级别相同:
  2. 检查两个引用绑定之间是否一个比另一个更好,如果其中一个不是引用绑定,或者两个绑定不可区分,
  3. 检查其中一个函数是否是模板专门化,而另一个则不是,那么如果这两个函数都是模板专门化的话。
  4. 检查其中一个专门化是否比另一个更专门化。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52428882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档