如何在结构中正确重载 < 运算符以启用在 C++ 中的集合中使用
How to properly overload < operator in a struct to enable use in a set in C++
我正在尝试在 C++ 中创建一组结构,该操作需要重载“<”运算符。
即使我确实找到了编译它的方法,它也没有被封装在结构中,因此看起来不适合 OO 设计。
我试过哪些有效:
#include <iostream>
#include <set>
struct Coordinate {
int x, y;
};
bool operator<(const Coordinate& l, const Coordinate& r) {
return l.x * l.y < r.x * r.y;
}
int main() {
std::set<Coordinate> mySet;
mySet.insert(Coordinate{ 5,5 });
}
我想做的是这样的:
#include <iostream>
#include <set>
struct Coordinate {
int x, y;
bool operator<(const Coordinate& other) {
return this->x * this->y < other.x * other.y;
}
};
int main() {
std::set<Coordinate> mySet;
mySet.insert(Coordinate{ 5,5 });
}
但是后者无法编译。
错误信息:
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xstddef(127,1): error C2678: binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)
1> with
1> [
1> _Ty=Coordinate
1> ]
1>C:\CppWorkspace\Dungeons of Doom\Dungeons of Doom\src\TestMain.cpp(7,7): message : could be 'bool Coordinate::operator <(const Coordinate &)'
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xstddef(127,1): message : while trying to match the argument list '(const _Ty, const _Ty)'
1> with
1> [
1> _Ty=Coordinate
1> ]
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xstddef(126): message : while compiling class template member function 'bool std::less<Coordinate>::operator ()(const _Ty &,const _Ty &) const'
1> with
1> [
1> _Ty=Coordinate
1> ]
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xutility(1469): message : see reference to function template instantiation 'bool std::less<Coordinate>::operator ()(const _Ty &,const _Ty &) const' being compiled
1> with
1> [
1> _Ty=Coordinate
1> ]
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xmemory(1318): message : see reference to class template instantiation 'std::less<Coordinate>' being compiled
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xmemory(1318): message : see reference to variable template 'const bool is_empty_v<std::less<Coordinate> >' being compiled
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\set(54): message : see reference to class template instantiation 'std::_Tree<std::_Tset_traits<_Kty,_Pr,_Alloc,false>>' being compiled
1> with
1> [
1> _Kty=Coordinate,
1> _Pr=std::less<Coordinate>,
1> _Alloc=std::allocator<Coordinate>
1> ]
1>C:\CppWorkspace\Dungeons of Doom\Dungeons of Doom\src\TestMain.cpp(17): message : see reference to class template instantiation 'std::set<Coordinate,std::less<Coordinate>,std::allocator<Coordinate>>' being compiled
我是 C++ 的新手,想知道是否有办法做这样的事情。
你看编译错误了吗?
如其所说,方法需要是const
bool operator<(const Coordinate& other) const { // const the < operator
return this->x * this->y < other.x * other.y;
}
比较运算符最好是友元函数。
#include <iostream>
#include <set>
struct Coordinate {
int x, y;
friend bool operator<(const Coordinate& lhs, const Coordinate& rhs) {
return lhs.x * lhs.y < rhs.x * rhs.y;
}
};
int main() {
std::set<Coordinate> mySet;
mySet.insert(Coordinate{ 5,5 });
}
operator<
需要 const
,但更大的问题是操作员没有执行正确的 strict weak ordering that's mentioned in the Compare 命名要求。
考虑这段代码:
#include <iostream>
#include <set>
struct Coordinate {
int x, y;
Coordinate(int X, int Y) : x(X), y(Y) {}
bool operator<(const Coordinate& other) const {
return this->x * this->y < other.x * other.y;
}
};
int main() {
std::set<Coordinate> mySet;
mySet.emplace(1, 5);
mySet.emplace(5, 1);
std::cout << mySet.size() << '\n';
}
这将输出 1
,因为第二个 Coordinate
在使用 operator<
时将被视为等于第一个 1
。
正确的版本可能如下所示:
bool operator<(const Coordinate& other) const {
return x==other.x ? y < other.y : x < other.x;
}
或者更好的是,使用 <tuple>
中的 std::tie
可以大大简化此过程:
bool operator<(const Coordinate& other) const {
return std::tie(x, y) < std::tie(other.x, other.y);
}
我正在尝试在 C++ 中创建一组结构,该操作需要重载“<”运算符。
即使我确实找到了编译它的方法,它也没有被封装在结构中,因此看起来不适合 OO 设计。
我试过哪些有效:
#include <iostream>
#include <set>
struct Coordinate {
int x, y;
};
bool operator<(const Coordinate& l, const Coordinate& r) {
return l.x * l.y < r.x * r.y;
}
int main() {
std::set<Coordinate> mySet;
mySet.insert(Coordinate{ 5,5 });
}
我想做的是这样的:
#include <iostream>
#include <set>
struct Coordinate {
int x, y;
bool operator<(const Coordinate& other) {
return this->x * this->y < other.x * other.y;
}
};
int main() {
std::set<Coordinate> mySet;
mySet.insert(Coordinate{ 5,5 });
}
但是后者无法编译。
错误信息:
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xstddef(127,1): error C2678: binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)
1> with
1> [
1> _Ty=Coordinate
1> ]
1>C:\CppWorkspace\Dungeons of Doom\Dungeons of Doom\src\TestMain.cpp(7,7): message : could be 'bool Coordinate::operator <(const Coordinate &)'
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xstddef(127,1): message : while trying to match the argument list '(const _Ty, const _Ty)'
1> with
1> [
1> _Ty=Coordinate
1> ]
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xstddef(126): message : while compiling class template member function 'bool std::less<Coordinate>::operator ()(const _Ty &,const _Ty &) const'
1> with
1> [
1> _Ty=Coordinate
1> ]
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xutility(1469): message : see reference to function template instantiation 'bool std::less<Coordinate>::operator ()(const _Ty &,const _Ty &) const' being compiled
1> with
1> [
1> _Ty=Coordinate
1> ]
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xmemory(1318): message : see reference to class template instantiation 'std::less<Coordinate>' being compiled
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\xmemory(1318): message : see reference to variable template 'const bool is_empty_v<std::less<Coordinate> >' being compiled
1>C:\Program Files (x86)\Microsoft Visual Studio19\Preview\VC\Tools\MSVC.25.28508\include\set(54): message : see reference to class template instantiation 'std::_Tree<std::_Tset_traits<_Kty,_Pr,_Alloc,false>>' being compiled
1> with
1> [
1> _Kty=Coordinate,
1> _Pr=std::less<Coordinate>,
1> _Alloc=std::allocator<Coordinate>
1> ]
1>C:\CppWorkspace\Dungeons of Doom\Dungeons of Doom\src\TestMain.cpp(17): message : see reference to class template instantiation 'std::set<Coordinate,std::less<Coordinate>,std::allocator<Coordinate>>' being compiled
我是 C++ 的新手,想知道是否有办法做这样的事情。
你看编译错误了吗?
如其所说,方法需要是const
bool operator<(const Coordinate& other) const { // const the < operator
return this->x * this->y < other.x * other.y;
}
比较运算符最好是友元函数。
#include <iostream>
#include <set>
struct Coordinate {
int x, y;
friend bool operator<(const Coordinate& lhs, const Coordinate& rhs) {
return lhs.x * lhs.y < rhs.x * rhs.y;
}
};
int main() {
std::set<Coordinate> mySet;
mySet.insert(Coordinate{ 5,5 });
}
operator<
需要 const
,但更大的问题是操作员没有执行正确的 strict weak ordering that's mentioned in the Compare 命名要求。
考虑这段代码:
#include <iostream>
#include <set>
struct Coordinate {
int x, y;
Coordinate(int X, int Y) : x(X), y(Y) {}
bool operator<(const Coordinate& other) const {
return this->x * this->y < other.x * other.y;
}
};
int main() {
std::set<Coordinate> mySet;
mySet.emplace(1, 5);
mySet.emplace(5, 1);
std::cout << mySet.size() << '\n';
}
这将输出 1
,因为第二个 Coordinate
在使用 operator<
时将被视为等于第一个 1
。
正确的版本可能如下所示:
bool operator<(const Coordinate& other) const {
return x==other.x ? y < other.y : x < other.x;
}
或者更好的是,使用 <tuple>
中的 std::tie
可以大大简化此过程:
bool operator<(const Coordinate& other) const {
return std::tie(x, y) < std::tie(other.x, other.y);
}