{"id":8844,"date":"2024-01-08T09:56:01","date_gmt":"2024-01-08T09:56:01","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=8844"},"modified":"2024-01-08T09:56:01","modified_gmt":"2024-01-08T09:56:01","slug":"the-autogenerated-equality-operator","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/the-autogenerated-equality-operator\/","title":{"rendered":"The autogenerated Equality Operator"},"content":{"rendered":"\n<p>You can define the three-way comparison operator or request it from the compiler with <code>=default<\/code>. But do you know that you can also define or request the equality operator in C++20?<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"397\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/TimelineCpp20-1-1030x397.png\" alt=\"\" class=\"wp-image-8847\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/TimelineCpp20-1-1030x397.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/TimelineCpp20-1-300x116.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/TimelineCpp20-1-768x296.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/TimelineCpp20-1-705x272.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/TimelineCpp20-1.png 1054w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>Before I dive into the autogenerated equality operator, I&#8217;d like to refresh your knowledge about the three-way comparison operator.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Three-Way Comparison Operator<\/h2>\n\n\n\n<p>You can define the three-way comparison operator or request it from the compiler with <code>=default<\/code>. You get all six comparison operators in both cases:<code>&nbsp;==,&nbsp;!=, &lt;, &lt;=, &gt;,<\/code> and <code>&gt;=<\/code>.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ threeWayComparison.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;compare&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> MyInt {\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> value;\n    <span style=\"color: #006699; font-weight: bold\">explicit<\/span> MyInt(<span style=\"color: #007788; font-weight: bold\">int<\/span> val)<span style=\"color: #555555\">:<\/span> value{val} { }\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">&lt;=&gt;<\/span>(<span style=\"color: #006699; font-weight: bold\">const<\/span> MyInt<span style=\"color: #555555\">&amp;<\/span> rhs) <span style=\"color: #006699; font-weight: bold\">const<\/span> {           <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)      <\/span>\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> value <span style=\"color: #555555\">&lt;=&gt;<\/span> rhs.value;\n    }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> MyDouble {\n    <span style=\"color: #007788; font-weight: bold\">double<\/span> value;\n    <span style=\"color: #006699; font-weight: bold\">explicit<\/span> constexpr MyDouble(<span style=\"color: #007788; font-weight: bold\">double<\/span> val)<span style=\"color: #555555\">:<\/span> value{val} { }\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">&lt;=&gt;<\/span>(<span style=\"color: #006699; font-weight: bold\">const<\/span> MyDouble<span style=\"color: #555555\">&amp;<\/span>) <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #555555\">=<\/span> <span style=\"color: #006699; font-weight: bold\">default<\/span>;   <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n};\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\nconstexpr <span style=\"color: #007788; font-weight: bold\">bool<\/span> isLessThan(<span style=\"color: #006699; font-weight: bold\">const<\/span> T<span style=\"color: #555555\">&amp;<\/span> lhs, <span style=\"color: #006699; font-weight: bold\">const<\/span> T<span style=\"color: #555555\">&amp;<\/span> rhs) {\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> lhs <span style=\"color: #555555\">&lt;<\/span> rhs;\n}\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> main() {\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>boolalpha <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>endl;\n    \n    MyInt <span style=\"color: #CC00FF\">myInt1<\/span>(<span style=\"color: #FF6600\">2011<\/span>);\n    MyInt <span style=\"color: #CC00FF\">myInt2<\/span>(<span style=\"color: #FF6600\">2014<\/span>);\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;isLessThan(myInt1, myInt2): &quot;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> isLessThan(myInt1, myInt2) <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>endl;\n              \n    MyDouble <span style=\"color: #CC00FF\">myDouble1<\/span>(<span style=\"color: #FF6600\">2011<\/span>);\n    MyDouble <span style=\"color: #CC00FF\">myDouble2<\/span>(<span style=\"color: #FF6600\">2014<\/span>);\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;isLessThan(myDouble1, myDouble2): &quot;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> isLessThan(myDouble1, myDouble2) <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>endl;          \n              \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>endl;\n              \n}\n<\/pre><\/div>\n\n\n\n<p>The user-defined (1) and the compiler-generated (2) three-way comparison operators work as expected.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"405\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/threeWayComparison-1030x405.png\" alt=\"\" class=\"wp-image-8851\" style=\"width:400px\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/threeWayComparison-1030x405.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/threeWayComparison-300x118.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/threeWayComparison-768x302.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/threeWayComparison-705x277.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/threeWayComparison.png 1341w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>But there are a few subtle differences in this case. The compiler-deduced return type for <code>MyInt <\/code>(1) supports strong ordering, and the compiler-deduced return type of <code>MyDouble<\/code> supports partial ordering. Floating pointer numbers only support partial ordering because floating-point values such as <a href=\"https:\/\/en.wikipedia.org\/wiki\/NaN\">NaN<\/a> (Not a Number) can not be ordered. For example, <code>NaN == NaN<\/code>&nbsp; is <code>false<\/code>.<\/p>\n\n\n\n<p>The compiler-generated three-way comparison operator needs the header <code>&lt;compare&gt;<\/code>, which is implicit<code> constexpr<\/code> and <code>noexcept<\/code>. Additionally, it performs a lexicographical comparison. Lexicographical comparison means that all base classes are compared left to right and all non-static members in their declaration order.<\/p>\n\n\n\n<p>Let&#8217;s assume I add a <code>std::unordered_set <\/code>to both classes <code>MyInt<\/code> and <code>MyDouble<\/code>. <\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">struct<\/span> MyInt {\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> value;\n    std<span style=\"color: #555555\">::<\/span>unordered_set<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> mySet;\n    <span style=\"color: #006699; font-weight: bold\">explicit<\/span> MyInt(<span style=\"color: #007788; font-weight: bold\">int<\/span> val)<span style=\"color: #555555\">:<\/span> value{val}, mySet{val} { }\n    <span style=\"color: #007788; font-weight: bold\">bool<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">&lt;=&gt;<\/span>(<span style=\"color: #006699; font-weight: bold\">const<\/span> MyInt<span style=\"color: #555555\">&amp;<\/span> rhs) <span style=\"color: #006699; font-weight: bold\">const<\/span> {\n        <span style=\"color: #006699; font-weight: bold\">if<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span> first <span style=\"color: #555555\">=<\/span> value <span style=\"color: #555555\">&lt;=&gt;<\/span> rhs.value; first <span style=\"color: #555555\">!=<\/span> <span style=\"color: #FF6600\">0<\/span>) <span style=\"color: #006699; font-weight: bold\">return<\/span> first;\n        <span style=\"color: #006699; font-weight: bold\">else<\/span> <span style=\"color: #006699; font-weight: bold\">return<\/span> mySet <span style=\"color: #555555\">&lt;=&gt;<\/span> rhs.mySet; \n    }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> MyDouble {\n    <span style=\"color: #007788; font-weight: bold\">double<\/span> value;\n    std<span style=\"color: #555555\">::<\/span>unordered_set<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">double<\/span><span style=\"color: #555555\">&gt;<\/span> mySet;\n    <span style=\"color: #006699; font-weight: bold\">explicit<\/span> MyDouble(<span style=\"color: #007788; font-weight: bold\">double<\/span> val)<span style=\"color: #555555\">:<\/span> value{val}, mySet{val} { }\n    <span style=\"color: #007788; font-weight: bold\">bool<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">&lt;=&gt;<\/span>(<span style=\"color: #006699; font-weight: bold\">const<\/span> MyDouble<span style=\"color: #555555\">&amp;<\/span>) <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #555555\">=<\/span> <span style=\"color: #006699; font-weight: bold\">default<\/span>;   \n};\n<\/pre><\/div>\n\n\n\n<p>Requesting or defining the three-way comparison fails because<code> std::unordered_set<\/code> does not support ordering.<code> std::unordered_set<\/code> only support equality comparison, and so does <code>MyInt<\/code> and <code>MyDouble<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Equality Operator<\/h2>\n\n\n\n<p>When you define or request the equality operator from the compiler with =<code>default<\/code>, you automatically<br>get the equality and inequality operators:<code> ==<\/code>, and<code> !=<\/code>.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ equalityOperator.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;tuple&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;unordered_set&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> MyInt {\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> value;\n    std<span style=\"color: #555555\">::<\/span>unordered_set<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> mySet;\n    <span style=\"color: #006699; font-weight: bold\">explicit<\/span> <span style=\"color: #CC00FF\">MyInt<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> val)<span style=\"color: #555555\">:<\/span> value{val}, mySet{val} { }\n    <span style=\"color: #007788; font-weight: bold\">bool<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">==<\/span>(<span style=\"color: #006699; font-weight: bold\">const<\/span> MyInt<span style=\"color: #555555\">&amp;<\/span> rhs) <span style=\"color: #006699; font-weight: bold\">const<\/span> {                 \n        <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>tie(value, mySet) <span style=\"color: #555555\">==<\/span> std<span style=\"color: #555555\">::<\/span>tie(rhs.value, rhs.mySet);\n    }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> MyDouble {\n    <span style=\"color: #007788; font-weight: bold\">double<\/span> value;\n    std<span style=\"color: #555555\">::<\/span>unordered_set<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">double<\/span><span style=\"color: #555555\">&gt;<\/span> mySet;\n    <span style=\"color: #006699; font-weight: bold\">explicit<\/span> MyDouble(<span style=\"color: #007788; font-weight: bold\">double<\/span> val)<span style=\"color: #555555\">:<\/span> value{val}, mySet{val} { }\n    <span style=\"color: #007788; font-weight: bold\">bool<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">==<\/span>(<span style=\"color: #006699; font-weight: bold\">const<\/span> MyDouble<span style=\"color: #555555\">&amp;<\/span>) <span style=\"color: #006699; font-weight: bold\">const<\/span> <span style=\"color: #555555\">=<\/span> <span style=\"color: #006699; font-weight: bold\">default<\/span>;   \n};\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\nconstexpr <span style=\"color: #007788; font-weight: bold\">bool<\/span> areEqual(<span style=\"color: #006699; font-weight: bold\">const<\/span> T<span style=\"color: #555555\">&amp;<\/span> lhs, <span style=\"color: #006699; font-weight: bold\">const<\/span> T<span style=\"color: #555555\">&amp;<\/span> rhs) {\n\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> lhs <span style=\"color: #555555\">==<\/span> rhs;\n}\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\nconstexpr <span style=\"color: #007788; font-weight: bold\">bool<\/span> areNotEqual(<span style=\"color: #006699; font-weight: bold\">const<\/span> T<span style=\"color: #555555\">&amp;<\/span> lhs, <span style=\"color: #006699; font-weight: bold\">const<\/span> T<span style=\"color: #555555\">&amp;<\/span> rhs) {\n\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> lhs <span style=\"color: #555555\">!=<\/span> rhs;\n}\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> main() {\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>boolalpha <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    \n    MyInt <span style=\"color: #CC00FF\">myInt1<\/span>(<span style=\"color: #FF6600\">2011<\/span>);\n    MyInt <span style=\"color: #CC00FF\">myInt2<\/span>(<span style=\"color: #FF6600\">2014<\/span>);\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;areEqual(myInt1, myInt2): &quot;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> areEqual(myInt1, myInt2) <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;areNotEqual(myInt1, myInt2): &quot;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> areNotEqual(myInt1, myInt2) <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;          \n              \n    MyDouble <span style=\"color: #CC00FF\">myDouble1<\/span>(<span style=\"color: #FF6600\">2011.0<\/span>);\n    MyDouble <span style=\"color: #CC00FF\">myDouble2<\/span>(<span style=\"color: #FF6600\">2014.0<\/span>);\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;areEqual(myDouble1, myDouble2): &quot;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> areEqual(myDouble1, myDouble2) <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;areNotEqual(myDouble1, myDouble2): &quot;<\/span>\n              <span style=\"color: #555555\">&lt;&lt;<\/span> areNotEqual(myDouble1, myDouble2) <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;           \n              \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n              \n}\n<\/pre><\/div>\n\n\n\n<p>Now, I can compare <code>MyInt<\/code> and <code>MyDouble<\/code> for equality and inequality.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"512\" height=\"305\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/equalityOperator.png\" alt=\"\" class=\"wp-image-8862\" style=\"width:400px\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/equalityOperator.png 512w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/12\/equalityOperator-300x179.png 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p>I applied a neat trick in the program <code>equalityOperator.cpp<\/code>. Can you spot it? <\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In the following example, I implemented the equality operator of <code>MyInt<\/code> by chaining the equality operators of <code>value<\/code> and <code>mySet<\/code>.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">struct<\/span> MyInt {\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> value;\n    std<span style=\"color: #555555\">::<\/span>unordered_set<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> mySet;\n    <span style=\"color: #006699; font-weight: bold\">explicit<\/span> MyInt(<span style=\"color: #007788; font-weight: bold\">int<\/span> val)<span style=\"color: #555555\">:<\/span> value{val}, mySet{val} { }\n    <span style=\"color: #007788; font-weight: bold\">bool<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">==<\/span>(<span style=\"color: #006699; font-weight: bold\">const<\/span> MyInt<span style=\"color: #555555\">&amp;<\/span> rhs) <span style=\"color: #006699; font-weight: bold\">const<\/span> {\n        <span style=\"color: #006699; font-weight: bold\">if<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span> first <span style=\"color: #555555\">=<\/span> value <span style=\"color: #555555\">==<\/span> rhs.value; first <span style=\"color: #555555\">!=<\/span> <span style=\"color: #FF6600\">0<\/span>) <span style=\"color: #006699; font-weight: bold\">return<\/span> first;\n        <span style=\"color: #006699; font-weight: bold\">else<\/span> <span style=\"color: #006699; font-weight: bold\">return<\/span> mySet <span style=\"color: #555555\">==<\/span> rhs.mySet; \n    }\n};\n<\/pre><\/div>\n\n\n\n<p>This is pretty ugly and error-prone if you have a class with more members<\/p>\n\n\n\n<p>On the contrary, I used <code>std::tie <\/code>to implement the equality operator in the program <code>equalityOperator.cpp<\/code>.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">struct<\/span> MyInt {\n    <span style=\"color: #007788; font-weight: bold\">int<\/span> value;\n    std<span style=\"color: #555555\">::<\/span>unordered_set<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span> mySet;\n    <span style=\"color: #006699; font-weight: bold\">explicit<\/span> <span style=\"color: #CC00FF\">MyInt<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> val)<span style=\"color: #555555\">:<\/span> value{val}, mySet{val} { }\n    <span style=\"color: #007788; font-weight: bold\">bool<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span><span style=\"color: #555555\">==<\/span>(<span style=\"color: #006699; font-weight: bold\">const<\/span> MyInt<span style=\"color: #555555\">&amp;<\/span> rhs) <span style=\"color: #006699; font-weight: bold\">const<\/span> {                 \n        <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>tie(value, mySet) <span style=\"color: #555555\">==<\/span> std<span style=\"color: #555555\">::<\/span>tie(rhs.value, rhs.mySet);\n    }\n};\n<\/pre><\/div>\n\n\n\n<p><code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/tuple\/tie\">std::tie<\/a><\/code> creates a tuple of lvalue references to its arguments. Finally, the created tuples are lexicographically compared. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next?<\/h2>\n\n\n\n<p>In my next post, I will continue my journey through C++20 and write about <code>std::span. std::span <\/code>represents an object that refers to a contiguous sequence of objects.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can define the three-way comparison operator or request it from the compiler with =default. But do you know that you can also define or request the equality operator in C++20? Before I dive into the autogenerated equality operator, I&#8217;d like to refresh your knowledge about the three-way comparison operator. The Three-Way Comparison Operator You [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":8847,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[462],"class_list":["post-8844","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-spaceship"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8844","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=8844"}],"version-history":[{"count":21,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8844\/revisions"}],"predecessor-version":[{"id":8887,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8844\/revisions\/8887"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/8847"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=8844"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=8844"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=8844"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}