Use an object as a key in std::set in C++
This post will discuss how to use an object as a key in a std::set in C++.
1. Using an object as a key in std::set function
We can use any object as a key in std::set. To facilitate this, we just need to overload the operator< for the class, as shown below:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <iostream> #include <set> template<typename T1, typename T2> class Pair { public: T1 x; T2 y; // constructor Pair(T1 x, T2 y) { this->x = x; this->y = y; } // overload `<` operator to use a `Pair` object as a key in a `std::set` bool operator<(Pair const &p) const { return x < p.x || (x == p.x && y < p.y); } }; int main() { std::set<Pair<std::string, int>> set = { {"A", 4}, {"B", 4}, {"C", 1}, {"A", 0}, {"B", 3} }; for (auto const &p: set) { std::cout << "{" << p.x << ":" << p.y << "}\n"; } return 0; } |
Output:
{A:0}
{A:4}
{B:3}
{B:4}
{C:1}
Notice that there is no need to overload the operator== as it is not used by std::set to detect equality. The operator< is used instead. Two elements a and b are considered equal if the expression !(a < b) && !(b < a) returns true, i.e., if two elements are both not less than the other, then they must be equal.
2. Using an object as a key in std::set with comparison object
We can avoid overloading the operator< for the class by using a comparator function object to specialize std::set, as shown below:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#include <iostream> #include <set> template<typename T1, typename T2> class Pair { public: T1 x; T2 y; // constructor Pair(T1 x, T2 y) { this->x = x; this->y = y; } }; struct comp { template<typename T> bool operator()(const T &lhs, const T &rhs) const { if (lhs.x == rhs.x) { return lhs.y < rhs.y; } return lhs.x < rhs.x; } }; int main() { std::set<Pair<std::string, int>, comp> set = { {"A", 4}, {"B", 4}, {"C", 1}, {"A", 0}, {"B", 3} }; for (auto const &p: set) { std::cout << "{" << p.x << ":" << p.y << "}\n"; } return 0; } |
Output:
{A:0}
{A:4}
{B:3}
{B:4}
{C:1}
In this version, two elements a and b are considered equivalent if the expression (!comp(a, b) && !comp(b, a)) returns true.
3. Using an object as a key in std::set by specializing std::less function
We can still override the default order of std::set and not pass the comparator function object to it by specializing std::less in the std namespace. This works as the default for the second template parameter of std::set is std::less, which will delegate to operator<.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <iostream> #include <set> template<typename T1, typename T2> class Pair { public: T1 x; T2 y; // constructor Pair(T1 x, T2 y) { this->x = x; this->y = y; } }; namespace std { template<typename T1, typename T2> struct less<Pair<T1, T2>> { bool operator()(const Pair<T1, T2> &l, const Pair<T1, T2> &r) const { return l.x < r.x || (l.x == r.x && l.y < r.y); } }; } int main() { std::set<Pair<std::string, int>> set = { {"A", 4}, {"B", 4}, {"C", 1}, {"A", 0}, {"B", 3} }; for (auto const &p: set) { std::cout << "{" << p.x << ":" << p.y << "}\n"; } return 0; } |
Output:
{A:0}
{A:4}
{B:3}
{B:4}
{C:1}
That’s all about using an object as a key in std::set in C++.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)