为什么 ADL 的运算符函数行为与其他函数不同?
Why ADL has a different behavior for operator function than other functions?
我以这种方式在NS_C
命名空间中创建了一个C
类:
#include <iostream>
namespace NS_C {
template <typename T>
class C {
public:
C operator+(long) {
std::cout << "NS_C::C::operator+n";
return *this;
}
void not_operator(C<T>, long) {
std::cout << "NS_C::C::not_operatorn";
}
void call() {
*this + 0;
not_operator(*this, 0);
}
};
}
函数call
应该调用NS_C::C::operator+
然后NS_C::C::not_operator
。为了测试此行为,我运行了这个小程序:
int main()
{
NS_C::C<int> ci;
ci.call();
return 0;
}
输出是我期望的:
> g++ -o example example.cpp && ./example
NS_C::C::operator+
NS_C::C::not_operator
现在,我想在单独的命名空间NS_A
中创建一个新的类A
,并向此命名空间添加两个operator+
和not_operator
函数的泛型重载:
#include <iostream>
namespace NS_A {
class A {};
template <typename T>
T operator+(T t, int)
{
std::cout << "NS_A::operator+n";
return t;
}
template <typename T>
void not_operator(T, int)
{
std::cout << "NS_A::not_operatorn";
}
}
多亏了 ADL,从NS_C::C<NS_A>
对象调用call
成员函数将调用重载的NS_A::operator+
,因为它匹配得更好(第二个参数在NS_A::operator+
中int
,在NS_C::C::operator+
中long
(。 但是,我不明白为什么我的not_operator
函数不会发生相同的行为。实际上,NS_C::C::not_operator
仍将从call
函数中调用。
让我们使用以下主函数:
int main()
{
NS_C::C<NS_A::A> ca;
ca.call();
return 0;
}
我有以下输出:
NS_A::operator+
NS_C::C::not_operator
为什么在这种情况下不调用NS_A::not_operator
?
以下是重现该问题的完整代码:
#include <iostream>
namespace NS_A {
class A {};
template <typename T>
T operator+(T t, int)
{
std::cout << "NS_A::operator+n";
return t;
}
template <typename T>
void not_operator(T, int)
{
std::cout << "NS_A::not_operatorn";
}
}
namespace NS_C {
template <typename T>
class C {
public:
C operator+(long) {
std::cout << "NS_C::C::operator+n";
return *this;
}
void not_operator(C<T>, long) {
std::cout << "NS_C::C::not_operatorn";
}
void call() {
*this + 0;
not_operator(*this, 0);
}
};
}
int main()
{
NS_C::C<int> ci;
ci.call();
NS_C::C<NS_A::A> ca;
ca.call();
return 0;
}
来自 overload_resolution#Call_to_an_overloaded_operator:
我们有重载运算符的候选重载集:
1( 成员候选:如果 T1是一个完整的类或当前正在定义的类,则成员候选集是 T1::operator@ 的限定名称查找的结果。在所有其他情况下,成员候选项集为空。
2( 非成员候选:对于运算符重载允许非成员窗体的运算符,在表达式上下文中查找operator@的非限定名称找到的所有声明(可能涉及 ADL(,但成员函数声明将被忽略,并且不阻止查找继续进入下一个封闭范围。如果二元运算符的操作数或一元运算符的唯一操作数都具有枚举类型,则查找集中成为非成员候选项的唯一函数是其参数具有该枚举类型(或对该枚举类型的引用(的函数
而对于另一个,我们只有unqualified_lookup
unqualified_lookup#中甚至还有一个例子Overloaded_operator 显示operator+(a, a)
和a + a
之间的差异
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- 保留对其他类的成员函数的引用
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 如何在其他文件中使用函数
- C++变量名(可以将 main 声明为变量,但对于其他函数名称则不然)
- 如何封装一个函数,以便它只能由同一类中的一个其他函数调用?
- 为什么 memcpy() 和其他类似的函数使用汇编?
- 为什么 c++ 中的 main() 函数不采用除 int 和 void 之外的任何其他返回类型
- 泛型枚举和其他类型的重载模板函数
- error dllimport 函数的定义不允许在一个特定的联合中,而其他类、结构和联合将按预期导出
- 将基类的成员函数重载到其他派生类C++
- 如何在其他类中使用参数化构造函数制作类的对象?
- 为什么 ADL 的运算符函数行为与其他函数不同?
- 没有头文件如何使用c ++调用其他模块中的函数?
- 在C++单元测试上下文中,抽象基类是否应将其他抽象基类作为函数参数
- 如何制作 cmakelists.txt编译使用在其他地方声明和实现的函数和类的 CPP
- 成员函数不能为集合迭代器和const_iterator的输入重载(但可以为其他 STL 迭代器重载)
- 通过向构造函数其他对象引用页面来创建对象