{"id":5837,"date":"2020-01-24T08:00:20","date_gmt":"2020-01-24T08:00:20","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-20-define-the-concept-equal-and-ordering\/"},"modified":"2023-06-26T09:55:55","modified_gmt":"2023-06-26T09:55:55","slug":"c-20-define-the-concept-equal-and-ordering","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-20-define-the-concept-equal-and-ordering\/","title":{"rendered":"C++20: Define the Concepts Equal and Ordering"},"content":{"rendered":"<p><a href=\"http:\/\/bit.ly\/2NL0yJN\">In my last post<\/a>, I defined the concept <span style=\"font-family: 'courier new', courier;\">Equal<\/span>. Now, I go one step further and use the concept <span style=\"font-family: 'courier new', courier;\">Equal<\/span> to define the concept <span style=\"font-family: 'courier new', courier;\">Ordering<\/span>.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5808\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/11\/TimelineCpp20Concepts.png\" alt=\"TimelineCpp20Concepts\" width=\"650\" height=\"255\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/11\/TimelineCpp20Concepts.png 954w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/11\/TimelineCpp20Concepts-300x118.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/11\/TimelineCpp20Concepts-768x301.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>Here is a short reminder of where I ended with my last post. I defined the concept of <span style=\"font-family: 'courier new', courier;\">Equal<\/span> and a function <span style=\"font-family: 'courier new', courier;\">areEqual<\/span> to use it.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #cc00ff;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>typename <span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #cc00ff;\">concept<\/span> <span style=\"color: #007788; font-weight: bold;\">Equal<\/span> <span style=\"color: #000000; font-weight: bold;\">=<\/span>\r\n    requires(<span style=\"color: #007788; font-weight: bold;\">T<\/span> a, <span style=\"color: #007788; font-weight: bold;\">T<\/span> b) {\r\n        { a <span style=\"color: #555555;\">==<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> bool;\r\n        { a <span style=\"color: #555555;\">!=<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> bool;\r\n};\r\n\r\n\r\n<span style=\"color: #cc00ff;\">bool<\/span> areEqual(<span style=\"color: #007788; font-weight: bold;\">Equal<\/span> auto fir, <span style=\"color: #007788; font-weight: bold;\">Equal<\/span> auto sec) {                       \r\n  return fir <span style=\"color: #555555;\">==<\/span> sec;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h3>My Wrong Usage of the Concept <span style=\"font-family: 'courier new', courier;\">Equal<\/span><\/h3>\n<p>I used the concept of <span style=\"font-family: 'courier new', courier;\">Equal<\/span>&nbsp;in my last post in the wrong way. The concept <span style=\"font-family: 'courier new', courier;\">Equal<\/span> requires that <span style=\"font-family: 'courier new', courier;\">a<\/span> and <span style=\"font-family: 'courier new', courier;\">b<\/span> have the same type but the function <span style=\"font-family: 'courier new', courier;\">areEqual<\/span> allows fir and sec to be different types that both support the concept <span style=\"font-family: 'courier new', courier;\">Equal<\/span>. Using a constrained template parameter instead of placeholder syntax solves the issue:<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #cc00ff;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">Equal<\/span> <span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #cc00ff;\">bool<\/span> areEqual(<span style=\"color: #007788; font-weight: bold;\">T<\/span> fir, <span style=\"color: #007788; font-weight: bold;\">T<\/span> sec) {\r\n    fir <span style=\"color: #555555;\">==<\/span> sec;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Now, <span style=\"font-family: 'courier new', courier;\">fir<\/span> and <span style=\"font-family: 'courier new', courier;\">sec<\/span> must have the same type.&nbsp;<\/p>\n<p>Thanks a lot to Corentin Jabot&nbsp;for pointing out this inconsistency.&nbsp;<\/p>\n<p>Additionally, the concept <span style=\"font-family: 'courier new', courier;\">Equal<\/span> should not check if the equal and unequal operator returns a <span style=\"font-family: 'courier new', courier;\">bool<\/span> but something implicitly or explicitly convertible to a <span style=\"font-family: 'courier new', courier;\">bool<\/span>. Here we are.&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #cc00ff;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>typename <span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #cc00ff;\">concept<\/span> <span style=\"color: #007788; font-weight: bold;\">Equal<\/span> <span style=\"color: #000000; font-weight: bold;\">=<\/span>\r\n    requires(<span style=\"color: #007788; font-weight: bold;\">T<\/span> a, <span style=\"color: #007788; font-weight: bold;\">T<\/span> b) {\r\n        { a <span style=\"color: #555555;\">==<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">!=<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I have to add. <span style=\"font-family: 'courier new', courier;\"><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/concepts\/convertible_to\">std::convertible_to<\/a>&nbsp;<\/span>is a concept and requires the header <span style=\"font-family: 'courier new', courier;\">&lt;concepts&gt;<\/span>.&nbsp;&nbsp;<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #cc00ff;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #007788; font-weight: bold;\">From<\/span>, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #007788; font-weight: bold;\">To<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #cc00ff;\">concept<\/span> convertible_to <span style=\"color: #000000; font-weight: bold;\">=<\/span>\r\n  std<span style=\"color: #000000; font-weight: bold;\">::<\/span>is_convertible_v<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">From<\/span>, <span style=\"color: #007788; font-weight: bold;\">To<\/span><span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n  requires(<span style=\"color: #007788; font-weight: bold;\">From<\/span> (<span style=\"color: #555555;\">&amp;<\/span>f)<span style=\"color: #336666;\">()<\/span>) {\r\n    static_cast<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">To<\/span><span style=\"color: #555555;\">&gt;<\/span>(f<span style=\"color: #336666;\">()<\/span>);\r\n  };\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The C++ 20 standard has already defined two concepts for equality comparing:<\/p>\n<ul>\n<li><span style=\"font-family: 'courier new', courier;\"><strong>std::equality_comparabl<\/strong>e<\/span>: corresponds to my concept&nbsp;<span style=\"font-family: 'courier new', courier;\">Equal<\/span><\/li>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::equality_comparable_with<\/span><\/strong>: allows the comparison of values of different type; e.g.: <span style=\"font-family: 'courier new', courier;\">1.0 == 1.0f<\/span><\/li>\n<\/ul>\n<h2>The Challenge<\/h2>\n<p>I ended&nbsp;<a href=\"http:\/\/bit.ly\/2NL0yJN\">my last post<\/a> by presenting a part of the type class hierarchy of Haskell.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5814\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/11\/haskellsTypeclasses.png\" alt=\"haskellsTypeclasses\" width=\"400\" height=\"345\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/11\/haskellsTypeclasses.png 749w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/11\/haskellsTypeclasses-300x258.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>The class hierarchy shows that the type class <span style=\"font-family: 'courier new', courier;\">Ord<\/span>&nbsp;is a refinement of the type class&nbsp;<span style=\"font-family: 'courier new', courier;\">Eq<\/span>. This can elegantly be expressed in Haskell.<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #007788; font-weight: bold;\">Eq<\/span> a <span style=\"color: #006699; font-weight: bold;\">where<\/span>\r\n    (<span style=\"color: #555555;\">==<\/span>) <span style=\"color: #000000; font-weight: bold;\">::<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold;\">Bool<\/span>\r\n    (<span style=\"color: #555555;\">\/=<\/span>) <span style=\"color: #000000; font-weight: bold;\">::<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold;\">Bool<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #007788; font-weight: bold;\">Eq<\/span> a <span style=\"color: #000000; font-weight: bold;\">=&gt;<\/span> <span style=\"color: #007788; font-weight: bold;\">Ord<\/span> a <span style=\"color: #006699; font-weight: bold;\">where<\/span>\r\n    compare <span style=\"color: #000000; font-weight: bold;\">::<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold;\">Ordering<\/span>\r\n    (<span style=\"color: #555555;\">&lt;<\/span>) <span style=\"color: #000000; font-weight: bold;\">::<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold;\">Bool<\/span>\r\n    (<span style=\"color: #555555;\">&lt;=<\/span>) <span style=\"color: #000000; font-weight: bold;\">::<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold;\">Bool<\/span>\r\n    (<span style=\"color: #555555;\">&gt;<\/span>) <span style=\"color: #000000; font-weight: bold;\">::<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold;\">Bool<\/span>\r\n    (<span style=\"color: #555555;\">&gt;=<\/span>) <span style=\"color: #000000; font-weight: bold;\">::<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold;\">Bool<\/span>\r\n    max <span style=\"color: #000000; font-weight: bold;\">::<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> a\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Here is my challenge. Can I express such as relationship quite elegantly with concepts in C++20? For simplicity reasons, I ignore the functions <span style=\"font-family: 'courier new', courier;\">compare<\/span> and <span style=\"font-family: 'courier new', courier;\">max<\/span> of Haskell&#8217;s type class. Of course, I can.<\/p>\n<h2>The Concept <span style=\"font-family: 'courier new', courier;\">Ordering<\/span><\/h2>\n<p>Thanks to requires-expression, the definition of the concept <span style=\"font-family: 'courier new', courier;\">Ordering<\/span> looks quite similar to the definition of the type class <span style=\"font-family: 'courier new', courier;\">Equal<\/span>.&nbsp;&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #cc00ff;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span>typename <span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #cc00ff;\">concept<\/span> <span style=\"color: #007788; font-weight: bold;\">Ordering<\/span> <span style=\"color: #000000; font-weight: bold;\">=<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">Equal<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n    requires(<span style=\"color: #007788; font-weight: bold;\">T<\/span> a, <span style=\"color: #007788; font-weight: bold;\">T<\/span> b) {\r\n        { a <span style=\"color: #555555;\">&lt;=<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">&lt;<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">&gt;<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">&gt;=<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n    };\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Okay, let me try it out.<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555;\">\/\/<\/span> conceptsDefinitionOrdering<span style=\"color: #555555;\">.<\/span>cpp\r\n\r\n<span style=\"color: #555555;\">#<\/span>include <span style=\"color: #555555;\">&lt;<\/span>concepts<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #555555;\">#<\/span>include <span style=\"color: #555555;\">&lt;<\/span>iostream<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #555555;\">#<\/span>include <span style=\"color: #555555;\">&lt;<\/span>unordered_set<span style=\"color: #555555;\">&gt;<\/span>\r\n\r\n<span style=\"color: #cc00ff;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>typename <span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #cc00ff;\">concept<\/span> <span style=\"color: #007788; font-weight: bold;\">Equal<\/span> <span style=\"color: #000000; font-weight: bold;\">=<\/span>\r\n    requires(<span style=\"color: #007788; font-weight: bold;\">T<\/span> a, <span style=\"color: #007788; font-weight: bold;\">T<\/span> b) {\r\n        { a <span style=\"color: #555555;\">==<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">!=<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n    };\r\n\r\n\r\n<span style=\"color: #cc00ff;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span>typename <span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #cc00ff;\">concept<\/span> <span style=\"color: #007788; font-weight: bold;\">Ordering<\/span> <span style=\"color: #000000; font-weight: bold;\">=<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">Equal<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n    requires(<span style=\"color: #007788; font-weight: bold;\">T<\/span> a, <span style=\"color: #007788; font-weight: bold;\">T<\/span> b) {\r\n        { a <span style=\"color: #555555;\">&lt;=<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">&lt;<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">&gt;<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">&gt;=<\/span> b } <span style=\"color: #000000; font-weight: bold;\">-&gt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>bool<span style=\"color: #555555;\">&gt;<\/span>;\r\n    };\r\n\r\n<span style=\"color: #cc00ff;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">Equal<\/span> <span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #cc00ff;\">bool<\/span> areEqual(<span style=\"color: #007788; font-weight: bold;\">T<\/span> a, <span style=\"color: #007788; font-weight: bold;\">T<\/span> b) {\r\n    return a <span style=\"color: #555555;\">==<\/span> b;\r\n}\r\n\r\n<span style=\"color: #cc00ff;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">Ordering<\/span> <span style=\"color: #007788; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">T<\/span> getSmaller(<span style=\"color: #007788; font-weight: bold;\">T<\/span> a, <span style=\"color: #007788; font-weight: bold;\">T<\/span> b) {\r\n    return (a <span style=\"color: #555555;\">&lt;<\/span> b) <span style=\"color: #555555;\">?<\/span> a <span style=\"color: #007788; font-weight: bold;\">:<\/span> b;\r\n}\r\n    \r\n<span style=\"color: #cc00ff;\">int<\/span> main<span style=\"color: #336666;\">()<\/span> {\r\n  \r\n    std<span style=\"color: #000000; font-weight: bold;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>boolalpha <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>endl;\r\n  \r\n    std<span style=\"color: #000000; font-weight: bold;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"areEqual(1, 5): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> areEqual(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">5<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>endl;\r\n  \r\n    std<span style=\"color: #000000; font-weight: bold;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"getSmaller(1, 5): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> getSmaller(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">5<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>endl;\r\n  \r\n    std<span style=\"color: #000000; font-weight: bold;\">::<\/span>unordered_set<span style=\"color: #555555;\">&lt;<\/span>int<span style=\"color: #555555;\">&gt;<\/span> firSet{<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>};\r\n    std<span style=\"color: #000000; font-weight: bold;\">::<\/span>unordered_set<span style=\"color: #555555;\">&lt;<\/span>int<span style=\"color: #555555;\">&gt;<\/span> secSet{<span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">1<\/span>};\r\n  \r\n    std<span style=\"color: #000000; font-weight: bold;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"areEqual(firSet, secSet): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> areEqual(firSet, secSet) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>endl;\r\n  \r\n    <span style=\"color: #555555;\">\/\/<\/span> auto smallerSet <span style=\"color: #000000; font-weight: bold;\">=<\/span> getSmaller(firSet, secSet);\r\n  \r\n    std<span style=\"color: #000000; font-weight: bold;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #000000; font-weight: bold;\">::<\/span>endl;\r\n  \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The function <span style=\"font-family: 'courier new', courier;\">getSmaller<\/span> requires that both arguments <span style=\"font-family: 'courier new', courier;\">a<\/span> and <span style=\"font-family: 'courier new', courier;\">b<\/span> support the concept <span style=\"font-family: 'courier new', courier;\">Ordering,<\/span> and both have the same type. This requirement holds for numbers 1 and 5.&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5835\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrdering.png\" alt=\"equalAndOrdering\" width=\"400\" height=\"149\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrdering.png 1596w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrdering-300x112.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrdering-1024x381.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrdering-768x286.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrdering-1536x572.png 1536w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>Of course, a <span style=\"font-family: 'courier new', courier;\">std::unordered_set<\/span> does not support order. The actual MSVC compiler is very specific when I try to compile the line <span style=\"font-family: 'courier new', courier;\">auto smaller = getSmaller(firSet, secSet<\/span>) with the flag <span style=\"font-family: 'courier new', courier;\">\/std:c++latest<\/span>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5836\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrderingError.png\" alt=\"equalAndOrderingError\" width=\"650\" height=\"222\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrderingError.png 3125w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrderingError-300x102.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrderingError-1024x350.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrderingError-768x262.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrderingError-1536x524.png 1536w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/equalAndOrderingError-2048x699.png 2048w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>By the way. The error message is obvious: <span style=\"font-family: 'courier new', courier;\">the associated constraints are not satisfied<\/span>.<\/p>\n<p>Of course, the concept <span style=\"font-family: 'courier new', courier;\">Ordering<\/span> is already part of the C++20 standard.<\/p>\n<ul>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::three_way_comparable:&nbsp;<\/span><\/strong>corresponds to my concept<span style=\"font-family: 'courier new', courier;\">&nbsp;Ordering<\/span><span style=\"font-family: 'courier new', courier;\"><span style=\"font-family: 'courier new', courier;\"><br \/><\/span><\/span><\/li>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::three_way_comparable_with:&nbsp;<\/span><\/strong>allows the comparison of values of different type; e.g.: <span style=\"font-family: 'courier new', courier;\">1.0 &lt; 1.0f<\/span><\/li>\n<\/ul>\n<p>Maybe, you are irritated by the term three-way. With C++20, we get the three-way comparison operator, the spaceship operator. <span style=\"font-family: 'courier new', courier;\">&lt;=&gt;<\/span>. Here is the first overview: <a href=\"http:\/\/bit.ly\/2PKLKge\">C++20: The Core Language<\/a>. I will write about the three-way comparison operator in a future post.&nbsp;<\/p>\n<h3>&nbsp;<\/h3>\n<h3 style=\"color: #000000;\">Compiler Support<\/h3>\n<p>I learn new stuff by trying it out. Maybe, you don&#8217;t have an actual MSVC available. In this case, use the current GCC (trunk) on the Compiler Explorer. GCC supports the C++20 syntax for concepts. Here is the<span style=\"font-family: 'courier new', courier;\"> conceptsDefinitionOrdering.cpp<\/span> for further experiments:&nbsp;<a href=\"https:\/\/godbolt.org\/z\/uyVFX8\">https:\/\/godbolt.org\/z\/uyVFX8<\/a>.&nbsp;&nbsp;<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>When you want to define a concrete type that works well in the C++ ecosystem, you should define a type that &#8220;behaves link an <span style=\"font-family: 'courier new', courier;\">int<\/span>&#8220;. &nbsp;Such a concrete type could be copied and the result of the copy operation is independent of the original one and has the same value.&nbsp; Formally, your concrete type should be regular. In the<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-define-the-concept-regular-and-semiregular\"> next post,<\/a> I will define the concepts <span style=\"font-family: 'courier new', courier;\">Regular<\/span> and <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my last post, I defined the concept Equal. Now, I go one step further and use the concept Equal to define the concept Ordering.<\/p>\n","protected":false},"author":21,"featured_media":5808,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[415],"class_list":["post-5837","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-concepts"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5837","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=5837"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5837\/revisions"}],"predecessor-version":[{"id":6758,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5837\/revisions\/6758"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5808"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5837"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5837"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5837"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}