gpt4 book ai didi

c++ - 添加重载更改选择了哪个重载

转载 作者:IT老高 更新时间:2023-10-28 23:21:51 26 4
gpt4 key购买 nike

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

#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&)将同样特化,但 Overload 2 有一个空参数包,因此选择了 Overload 1。但是,如果我添加第三个重载:

#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) (Overload 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)被选中。

最佳答案

我认为这是一个 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. 检查两个引用绑定(bind)之间是否一个比另一个更好,然后如果一个不是引用绑定(bind)或者两个绑定(bind)不可区分,
  3. 检查一个函数是否是模板特化,而另一个不是,然后检查两者是否是模板特化
  4. 检查其中一个专业是否比另一个专业更专业。

关于c++ - 添加重载更改选择了哪个重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52428882/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com