[over.load]/1 中的注释有什么意义?

What's the relevance of the Note in [over.load]/1?

提问人:Enlico 提问时间:8/26/2022 更新时间:8/27/2022 访问量:89

问:

(你可能会把这个问题看作是这个问题的重复,但是,老实说,我还没有真正理解这个问题,所以我用我自己的措辞单独问。

[over.load]/1 显示:

并非所有函数声明都可以重载。此处指定了那些不能超载的内容。如果程序在同一作用域中包含两个这样的不可重载声明,则该程序的格式不正确。[注:此限制适用于作用域内的显式声明,以及此类声明与通过使用声明进行的声明之间的显式声明。它不适用于由于名称查找(例如,由于 using 指令)或重载解析(例如,对于运算符函数)而产生的函数集。— 尾注]

作为一个临时问题,我说“此限制”是指“并非所有函数声明都可以重载”这一事实是否正确?

如果是这样的话,那么我会推断,如果我创建一组“由于名称查找而制造的函数”的情况,那么即使它们在上面引用的段落后面的列表中指定,这些函数也可以重载,因为限制不适用。

但这到底意味着什么,知道它有什么用呢?

我非常清楚,我不能重载函数仅在返回类型上有所不同,正如这个错误的代码所证明的那样,

int f() { return 1; };
double f() { return 2; }; // compile-time error

而且我也知道,如果两个 s 中的一个在另一个命名空间中,但通过声明引入,也会发生相同的情况fusing

int f() { return 1; };
namespace n {
double f() { return 2; };
}
using n::f; // compile-time error

我认为上面的第一个片段是作用域中显式声明的示例,而第二个代码片段是此类声明和通过 using 声明进行的声明之间的示例。

但是,由于名称查找(例如,由于 using 指令)而制造的函数示例是什么?像这样的东西?

int f() { return 1; };
namespace n {
double f() { return 2; };
}
using namespace n; // no error, as n::f can be seen by name lookup, but it's not actually declared here

如果是这样的话,我应该从中推断出什么?该限制不适用,因此我可以重载这 2 个函数。这是什么意思?我写完上面的 5 行片段后,是否已经超载了它们?或者我需要打一个电话,比如?不过,在这种情况下,调用是模棱两可的。auto x = f()

我真的不明白那张纸条想说什么。

C++ 语言-律师 重载解析 using-directives using-declaration

评论

1赞 Language Lawyer 8/26/2022
我写完上面的 5 行片段后,是否已经超载了它们?它与过载的定义不匹配。我真的不明白那张纸条想说什么该查找可能会生成一个重载集,其函数就好像它们在查找范围内被非法重载一样。

答:

2赞 Brian Bi 8/26/2022 #1

在使用 using 指令的示例中,函数不会重载。重载在 [over.pre]/1 中定义:

当为同一作用域中的单个名称指定两个或多个不同的声明时,该名称被称为载,并且这些声明称为重载声明。...

两者不在同一范围内,因此它们不会过载。f

但是,如果尝试调用 ,则将从名称查找的结果形成一个重载集,并且它包含两个声明。总是制造过载集;它是在使用名称时创建的(而不仅仅是声明);这种制造可能会将多个功能带入同一个过载集,尽管这些功能相互过载是非法的。该注释指出,创建这样的重载集并非格式错误。ff

当然,过载解决可能不明确,导致程序格式不正确,但有一些方法可以使用格式正确的重载集。例如,以下为 A-OK:

int f() { return 1; };
namespace n {
double f() { return 2; };
}
using namespace n;
double (*fp)() = &f;

评论

1赞 Enlico 8/26/2022
重载解决可能不明确,导致程序格式错误,但也可能不明确。例如,似乎说重载分辨率在您显示的代码片段中并不模棱两可。但是,如果没有函数调用,它到底会发生在哪里呢?
0赞 Brian Bi 8/27/2022
@Enlico过载解决是在获取过载集的地址时完成的。虽然,现在我再看一遍,我想从技术上讲,它可能不是过载分辨率。eel.is/c++draft/over.over