error: no match for ‘operator==’, but indeed defined on base class
error: no match for ‘operator==’, but indeed defined on base class
struct BaseA {
auto operator==(const BaseA& other) const {return other.a == a;}
int a;
};
struct B {
int b;
};
struct A: public BaseA {
auto operator==(const B& other) const {return other.b == a;}
};
int main() {
A a{10};
a == a;
return 0;
}
它不会编译:
error: no match for ‘operator==’ (operand types are ‘A’ and ‘A’)
note: candidate: ‘auto A::operator==(const B&) const’
note: no known conversion for argument 1 from ‘A’ to ‘const B&’
未将 BaseA::operator==
列为候选人。
但是,如果我注释掉 A::operator==
方法,它会编译。
正因为如此,我认为比较运算符得到一些特殊处理,(有时为 child class 生成,有时不会,就像 rule-of-five 中的那些),但是在快速搜索结果并非如此。
运算符重载的一些规则呢?
auto operator==(const B& other) const
隐藏基数,使用using
struct A: public BaseA {
using BaseA::operator==;
auto operator==(const B& other) const {return other.b == a;}
};
这里的运算符没什么特别的,你会得到类似的错误:
struct BaseA {
auto foo(const BaseA& other) const {return other.a == a;}
int a;
};
struct B {
int b;
};
struct A: public BaseA {
auto foo(const B& other) const {return other.b == a;}
};
int main() {
A a{10};
a.foo(a);
}
编译器在 A
中找到 foo
并停在那里。如果您想同时拥有两者,则需要明确地将其拉入范围:
struct A: public BaseA {
auto foo(const B& other) const {return other.b == a;}
using BaseA::foo;
};
我找到了一个修复,没有写出 using
我在子 class:
中添加的每个比较运算符
使运算符成为非成员并将其拉出到 A
的封闭范围(在本例中为全局范围):
auto operator==(const A&, const B&)
如果您想访问 A
的私有成员或其基数 class 的受保护成员,您可以将操作员设为 A
的好友。 (与 B
相同。)
为什么有效
隐藏(意思是如果这个名字在一个范围内找到,它不会在下一个范围内查找,那些查找算法将在下一步中考虑) 不会阻止它工作,因为 对于运算符 ,执行两个单独的查找,随后合并:
For an operator used in expression (e.g., operator+ used in a+b) two separate lookups are performed: for the non-member operator overloads and for the member operator overloads (for the operators where both forms are permitted). Those sets are then merged with the built-in operator overloads on equal grounds.
-- cppreference
因此全局命名空间中的非成员 operator==
不会阻止搜索 BaseA::operator==
,它在成员运算符查找中搜索,从 A
开始(但有没有 operator==
现在),所以继续下一个范围,基础 class BaseA
.
这种修复方法对我来说很重要,因为我使用了一个强类型库,我只想为强类型添加一个运算符,包装一个整数。我正在使用库 ti 避免自己写出样板,但每次我添加一个运算符时,我都必须 use
库中的那个。
struct BaseA {
auto operator==(const BaseA& other) const {return other.a == a;}
int a;
};
struct B {
int b;
};
struct A: public BaseA {
auto operator==(const B& other) const {return other.b == a;}
};
int main() {
A a{10};
a == a;
return 0;
}
它不会编译:
error: no match for ‘operator==’ (operand types are ‘A’ and ‘A’)
note: candidate: ‘auto A::operator==(const B&) const’
note: no known conversion for argument 1 from ‘A’ to ‘const B&’
未将 BaseA::operator==
列为候选人。
但是,如果我注释掉 A::operator==
方法,它会编译。
正因为如此,我认为比较运算符得到一些特殊处理,(有时为 child class 生成,有时不会,就像 rule-of-five 中的那些),但是在快速搜索结果并非如此。
运算符重载的一些规则呢?
auto operator==(const B& other) const
隐藏基数,使用using
struct A: public BaseA {
using BaseA::operator==;
auto operator==(const B& other) const {return other.b == a;}
};
这里的运算符没什么特别的,你会得到类似的错误:
struct BaseA {
auto foo(const BaseA& other) const {return other.a == a;}
int a;
};
struct B {
int b;
};
struct A: public BaseA {
auto foo(const B& other) const {return other.b == a;}
};
int main() {
A a{10};
a.foo(a);
}
编译器在 A
中找到 foo
并停在那里。如果您想同时拥有两者,则需要明确地将其拉入范围:
struct A: public BaseA {
auto foo(const B& other) const {return other.b == a;}
using BaseA::foo;
};
我找到了一个修复,没有写出 using
我在子 class:
使运算符成为非成员并将其拉出到 A
的封闭范围(在本例中为全局范围):
auto operator==(const A&, const B&)
如果您想访问 A
的私有成员或其基数 class 的受保护成员,您可以将操作员设为 A
的好友。 (与 B
相同。)
为什么有效
隐藏(意思是如果这个名字在一个范围内找到,它不会在下一个范围内查找,那些查找算法将在下一步中考虑) 不会阻止它工作,因为 对于运算符 ,执行两个单独的查找,随后合并:
For an operator used in expression (e.g., operator+ used in a+b) two separate lookups are performed: for the non-member operator overloads and for the member operator overloads (for the operators where both forms are permitted). Those sets are then merged with the built-in operator overloads on equal grounds.
-- cppreference
因此全局命名空间中的非成员 operator==
不会阻止搜索 BaseA::operator==
,它在成员运算符查找中搜索,从 A
开始(但有没有 operator==
现在),所以继续下一个范围,基础 class BaseA
.
这种修复方法对我来说很重要,因为我使用了一个强类型库,我只想为强类型添加一个运算符,包装一个整数。我正在使用库 ti 避免自己写出样板,但每次我添加一个运算符时,我都必须 use
库中的那个。