像 operator<< 、 operator* 这样的成员函数需要 ADL 才能工作吗?
Does member function like operator<< , operator* need ADL to work?
我有一个代码片段(假设):
#include <iostream>
struct Pirate {
void song_name() {
std::cout << "Bink's Sake\n";
}
Pirate& operator*(Pirate const& other) {
// do something
return *this;
}
};
int main() {
Pirate p1{} p2{};
p1.song_name(); // does this use qualified or unqualifed name lookup?
p1 * p2;
std::cout << 5;
std::cout << 'a';
}
p1 * p2
是使用限定名称查找还是非限定名称查找或 ADL?
std::cout << 5
转换为 std::cout.operator<<(5);
std::cout << 'a'
转换为 std::operator<<(std::cout, 'a');
成员函数是否需要 ADL 才能工作?
以上两个语句是否使用限定或非限定名称查找或 ADL?
谢谢
运算符查找non-static成员函数如
std::cout.operator<<(5);
但如果它们有 non-member 变体,non-member 也可以通过非限定查找和 ADL 运行。所有这些一起构成了重载集。
为了使其正常工作,non-member 变体应该通过 ADL 找到,即放置在 class 的名称空间内,它们正在为其重载运算符。例如。要为您自己的 class 重载 operator<<
,您不能使用成员版本,因为第一个参数可能应该是从 std::ostream
派生的任何内容。那么 non-member 变体上的 ADL 是让它在任何地方都能工作的唯一方法。
如果名称所属的范围使用 scope-resolution 运算符 ( ::
) 或 成员访问运算符 (.
或 ->
)。
案例一
因此,当您写道:
p1.song_name(); //here p1.song_name is a qualified name
在上面的语句中,p1.song_name
是一个 限定名称,所以这里发生 限定查找。
案例二
接下来,当您写道:
p1 * p2;
以上语句等同于:
p1.operator*(p2);
因为你的 class Pirate
有一个重载的成员函数 operator*
,上面的语句将使用那个成员函数。上面的语句也使用了 qualified lookup 因为我们使用了 member access operator .
.
案例三
这里有语句:
std::cout << 5;
以上语句等同于:
std::cout.operator<<(5);
使用 限定查找 因为它有成员访问运算符 .
案例 4
这里我们看声明:
operator<<(std::cout, 'a');
此处使用了 ofstream
的 operator<<
的 char
重载。这使用 ADL 因为在这种情况下第一个参数具有 class 类型。因此,编译器还将查找定义了 cout
的命名空间。因此,对于此调用,编译器还会查找 std
命名空间并找到 char
重载。
我有一个代码片段(假设):
#include <iostream>
struct Pirate {
void song_name() {
std::cout << "Bink's Sake\n";
}
Pirate& operator*(Pirate const& other) {
// do something
return *this;
}
};
int main() {
Pirate p1{} p2{};
p1.song_name(); // does this use qualified or unqualifed name lookup?
p1 * p2;
std::cout << 5;
std::cout << 'a';
}
p1 * p2
是使用限定名称查找还是非限定名称查找或 ADL?
std::cout << 5
转换为 std::cout.operator<<(5);
std::cout << 'a'
转换为 std::operator<<(std::cout, 'a');
成员函数是否需要 ADL 才能工作? 以上两个语句是否使用限定或非限定名称查找或 ADL?
谢谢
运算符查找non-static成员函数如
std::cout.operator<<(5);
但如果它们有 non-member 变体,non-member 也可以通过非限定查找和 ADL 运行。所有这些一起构成了重载集。
为了使其正常工作,non-member 变体应该通过 ADL 找到,即放置在 class 的名称空间内,它们正在为其重载运算符。例如。要为您自己的 class 重载 operator<<
,您不能使用成员版本,因为第一个参数可能应该是从 std::ostream
派生的任何内容。那么 non-member 变体上的 ADL 是让它在任何地方都能工作的唯一方法。
如果名称所属的范围使用 scope-resolution 运算符 ( ::
) 或 成员访问运算符 (.
或 ->
)。
案例一
因此,当您写道:
p1.song_name(); //here p1.song_name is a qualified name
在上面的语句中,p1.song_name
是一个 限定名称,所以这里发生 限定查找。
案例二
接下来,当您写道:
p1 * p2;
以上语句等同于:
p1.operator*(p2);
因为你的 class Pirate
有一个重载的成员函数 operator*
,上面的语句将使用那个成员函数。上面的语句也使用了 qualified lookup 因为我们使用了 member access operator .
.
案例三
这里有语句:
std::cout << 5;
以上语句等同于:
std::cout.operator<<(5);
使用 限定查找 因为它有成员访问运算符 .
案例 4
这里我们看声明:
operator<<(std::cout, 'a');
此处使用了 ofstream
的 operator<<
的 char
重载。这使用 ADL 因为在这种情况下第一个参数具有 class 类型。因此,编译器还将查找定义了 cout
的命名空间。因此,对于此调用,编译器还会查找 std
命名空间并找到 char
重载。