{"id":5841,"date":"2020-01-30T20:51:14","date_gmt":"2020-01-30T20:51:14","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-20-define-the-concept-regular-and-semiregular\/"},"modified":"2023-06-26T09:55:44","modified_gmt":"2023-06-26T09:55:44","slug":"c-20-define-the-concept-regular-and-semiregular","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-20-define-the-concept-regular-and-semiregular\/","title":{"rendered":"C++20: Define the Concept Regular and SemiRegular"},"content":{"rendered":"<p><span style=\"color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">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&nbsp;<\/span><span style=\"color: #444444; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; font-family: 'courier new', courier;\">int<\/span><span style=\"color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">&#8220;. Formally, your concrete type should be regular. In this post, I define the concepts&nbsp;<\/span><span style=\"color: #444444; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; font-family: 'courier new', courier;\">Regular<\/span><span style=\"color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">&nbsp;and&nbsp;<\/span><span style=\"color: #444444; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; font-family: 'courier new', courier;\">SemiRegular<\/span><span style=\"color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">.<\/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><span style=\"font-family: 'courier new', courier;\">Regular<\/span> and <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span> are essential ideas in C++. Sorry, I have to say concepts. For example, the rule T.46 from the C++ Core Guidelines: <a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-regular\">T.46: Require template arguments to be at least&nbsp;<span style=\"font-family: 'courier new', courier;\">Regular&nbsp;<\/span>or&nbsp;<span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span><\/a>. Only one important question is left to answer: What are <span style=\"font-family: 'courier new', courier;\">Regular<\/span> or <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span> types? Before I dive into the details, this is the informal answer:&nbsp;&nbsp;<\/p>\n<ul>\n<li>A regular type&nbsp;<span style=\"color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">&#8220;behaves link an&nbsp;<\/span><span style=\"color: #444444; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; font-family: 'courier new', courier;\">int<\/span><span style=\"color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">&#8220;.&nbsp; It could be copied and the result of the copy operation is independent of the original one and has the same value.&nbsp;<\/span><\/li>\n<\/ul>\n<p>Okay, let me be more formal. A <span style=\"font-family: 'courier new', courier;\">Regular<\/span> type is also a <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span> type. Consequentially I start with a <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span> type.&nbsp;<\/p>\n<h2 style=\"color: #000000;\"><span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span><\/h2>\n<p>A <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span> type has to support the&nbsp;<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors-assignments-and-desctructors\" style=\"background-color: #ffffff; color: #00466e; text-decoration: underline; outline: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;\">rule of six<\/a><span style=\"color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\"> and <\/span>be swappable.&nbsp;<\/p>\n<ul style=\"margin-top: 0px; margin-bottom: 10px; color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff;\">\n<li>Default constructor: <span style=\"font-family: 'courier new', courier;\">X()<\/span><\/li>\n<li>Copy constructor:&nbsp;<span style=\"font-family: 'courier new', courier;\">X(const X&amp;)<\/span><\/li>\n<li>Copy assignment:&nbsp;<span style=\"font-family: 'courier new', courier;\">operator=(const X&amp;)<\/span><\/li>\n<li>Move constructor:&nbsp;<span style=\"font-family: 'courier new', courier;\">X(X&amp;&amp;)<\/span><\/li>\n<li>Move assignment:&nbsp;<span style=\"font-family: 'courier new', courier;\">operator=(X&amp;&amp;)<\/span><\/li>\n<li>Destructor:&nbsp;<span style=\"font-family: 'courier new', courier;\">~X()<\/span><\/li>\n<li>swappable: <span style=\"font-family: 'courier new', courier;\">swap(X&amp;, Y&amp;)<\/span><\/li>\n<\/ul>\n<p>This was easy. Thanks to the type-traits library, defining the corresponding concepts is a no-brainer. Let me first define the corresponding type-trait <span style=\"font-family: 'courier new', courier;\">isSemiRegular<\/span> and then use it to define the concept <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span>.<\/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: #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>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> isSemiRegular<span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">bool<\/span>,\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_default_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_copy_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_copy_assignable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_move_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_move_assignable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_destructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_swappable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&gt;<\/span>{};\r\n\r\n\r\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>\r\nconcept SemiRegular <span style=\"color: #555555;\">=<\/span> isSemiRegular<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value;\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Let&#8217;s continue.<\/p>\n<\/p>\n<h2><span style=\"font-family: 'courier new', courier;\">Regular<\/span><\/h2>\n<p>Only one little step, and I&#8217;m done with the concept <span style=\"font-family: 'courier new', courier;\">Regular<\/span>. Additionally, to the concept <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span> the concept <span style=\"font-family: 'courier new', courier;\">Regular<\/span> requires that the type is equally comparable. I already defined in my <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-define-the-concept-equal-and-ordering\">last post<\/a> the concept <span style=\"font-family: 'courier new', courier;\">Equal<\/span>.&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;\">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>Let me reuse the concept <span style=\"font-family: 'courier new', courier;\">Equal<\/span> to define the concept <span style=\"font-family: 'courier new', courier;\">Regular<\/span>.<\/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: #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>\r\nconcept Regular <span style=\"color: #555555;\">= <\/span>Equal&lt;T&gt; &amp;&amp; <br \/>                  SemiRegular&lt;T&gt;;<span style=\"color: #555555;\"><br \/><\/span><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Now, I&#8217;m curious. How are <span style=\"font-family: 'courier new', courier;\">SemiRegular<\/span> and <span style=\"font-family: 'courier new', courier;\">Regular<\/span> defined in C++20?<\/p>\n<h3>The concepts<span style=\"font-family: courier new, courier;\"> regular<\/span> and <span style=\"font-family: courier new, courier;\">semiregular <\/span>in C++20<\/h3>\n<p>&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: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\nconcept movable <span style=\"color: #555555;\">=<\/span> is_object_v<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> move_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\nassignable_from<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&amp;<\/span>, T<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> swappable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>;\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\nconcept copyable <span style=\"color: #555555;\">=<\/span> copy_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> movable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> assignable_from<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&amp;<\/span>, <span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">&amp;&gt;<\/span>;\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\nconcept semiregular <span style=\"color: #555555;\">=<\/span> copyable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> default_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>;\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\nconcept regular <span style=\"color: #555555;\">=<\/span> semiregular<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> equality_comparable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>;\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>There is no reason to define the concept <span style=\"font-family: courier new, courier;\">Regular<\/span> and <span style=\"font-family: courier new, courier;\">SemiRegular<\/span> but to explain it.<\/p>\n<p>Interestingly, the concept <span style=\"font-family: courier new, courier;\">regular<\/span> is similar to my concept <span style=\"font-family: courier new, courier;\">Regular<\/span> but the concept <span style=\"font-family: courier new, courier;\">semiregular<\/span> is composed of more elementary concepts such as <span style=\"font-family: courier new, courier;\">copyable<\/span> and <span style=\"font-family: courier new, courier;\">moveable<\/span>. The concept <span style=\"font-family: courier new, courier;\">movable<\/span> is based on the function<span style=\"font-family: courier new, courier;\"> <\/span><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/is_object\"><span style=\"font-family: courier new, courier;\">is_object<\/span><\/a> from the type-traits library. From the referenced page, here is a possible implementation of the type-traits <span style=\"font-family: courier new, courier;\">is_object<\/span>.<\/p>\n<p>&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: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> is_object <span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">bool<\/span>,\r\n                     std<span style=\"color: #555555;\">::<\/span>is_scalar<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">||<\/span>\r\n                     std<span style=\"color: #555555;\">::<\/span>is_array<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value  <span style=\"color: #555555;\">||<\/span>\r\n                     std<span style=\"color: #555555;\">::<\/span>is_union<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value  <span style=\"color: #555555;\">||<\/span>\r\n                     std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value<span style=\"color: #555555;\">&gt;<\/span> {};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The final step in my post is missing. Let me try it out.<\/p>\n<h3>Usage for the concepts <span style=\"font-family: courier new, courier;\">Regular<\/span> and <span style=\"font-family: courier new, courier;\">regular <\/span><\/h3>\n<p>To simplify it, the function templates b<span style=\"font-family: courier new, courier;\">ehavesLikeAnInt<\/span> and b<span style=\"font-family: courier new, courier;\">ehavesLikeAnInt2<\/span> check if the arguments &#8220;behaves like an<span style=\"font-family: courier new, courier;\"> int<\/span>&#8220;. This means my concept Regular and the C++20 concept regular is used to establish the requirement.<span style=\"font-family: courier new, courier;\"><br \/><\/span><\/p>\n<p><span style=\"font-family: courier new, courier;\"><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/is_object\"><\/a><\/span><\/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: #0099ff; font-style: italic;\">\/\/ regularSemiRegular.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;concepts&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;utility&gt;<\/span>\r\n\r\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>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> isSemiRegular<span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">bool<\/span>,\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_default_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_copy_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_copy_assignable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_move_constructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_move_assignable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_destructible<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                      std<span style=\"color: #555555;\">::<\/span>is_swappable<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&gt;<\/span>{};\r\n\r\n\r\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>\r\nconcept SemiRegular <span style=\"color: #555555;\">=<\/span> isSemiRegular<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value;\r\n\r\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>\r\nconcept Equal <span style=\"color: #555555;\">=<\/span>\r\n    requires(T a, T b) {\r\n        { a <span style=\"color: #555555;\">==<\/span> b } <span style=\"color: #555555;\">-&gt;<\/span> std<span style=\"color: #555555;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">bool<\/span><span style=\"color: #555555;\">&gt;<\/span>;\r\n        { a <span style=\"color: #555555;\">!=<\/span> b } <span style=\"color: #555555;\">-&gt;<\/span> std<span style=\"color: #555555;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">bool<\/span><span style=\"color: #555555;\">&gt;<\/span>;\r\n};\r\n\r\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>                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\nconcept Regular <span style=\"color: #555555;\">=<\/span> Equal<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> \r\n                  SemiRegular<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>;\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span>Regular T<span style=\"color: #555555;\">&gt;                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span><\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> behavesLikeAnInt(T) {\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>regular T<span style=\"color: #555555;\">&gt;                         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span><\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> behavesLikeAnInt2(T) {\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> EqualityComparable { };                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>                                          \r\n<span style=\"color: #007788; font-weight: bold;\">bool<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">==<\/span> (EqualityComparable <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span>, EqualityComparable <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span>) { <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #336666;\">true<\/span>; }\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> NotEqualityComparable { };                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> myInt{};\r\n    behavesLikeAnInt(myInt);\r\n    behavesLikeAnInt2(myInt);\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> myVec{};\r\n    behavesLikeAnInt(myVec);\r\n    behavesLikeAnInt2(myVec);\r\n\r\n    EqualityComparable equComp;\r\n    behavesLikeAnInt(equComp);\r\n    behavesLikeAnInt2(equComp);\r\n\r\n    NotEqualityComparable notEquComp;             <span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n    behavesLikeAnInt(notEquComp);                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (6)<\/span>\r\n    behavesLikeAnInt2(notEquComp);                 <span style=\"color: #0099ff; font-style: italic;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ (7)<\/span><\/span>\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I combined all pieces from the previous code snippets to get the concept <span style=\"font-family: courier new, courier;\">Regular (Zeile 1)<\/span>. The functions behavesLikeAnInt (line 2) and behaves <span style=\"font-family: courier new, courier;\">behavesLikeAnInt2<\/span> (line 3) use both concepts. As the name suggests, the type <span style=\"font-family: courier new, courier;\">EqualityComparable<\/span> (line 4) supports equality but not the type <span style=\"font-family: courier new, courier;\">NotEqualityComparable <\/span>(line 5). Using the type <span style=\"font-family: courier new, courier;\">NotEqualityComparable<\/span> in both functions (lines 6 and 7) is the most interesting part.<\/p>\n<h4>GCC<\/h4>\n<p>If you want to see the program in action, use the link to Compiler Explorer: <a href=\"https:\/\/godbolt.org\/z\/XAJ2w3\">https:\/\/godbolt.org\/z\/XAJ2w3<\/a>. The error message in the Compiler Explorer with GCC is very accurate but a little overwhelming. This is probably due to the fact that both concepts failed, concepts are still in an early implementation stage, and the online tools are not as comfortable as a console.<\/p>\n<h5>The Concept <span style=\"font-family: courier new, courier;\">Regular<\/span><\/h5>\n<p>Essentially this is the message from my failed concept <span style=\"font-family: courier new, courier;\">Regular<\/span> (line 6) using the Compiler Explorer.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5838\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/RegularError.png\" alt=\"RegularError\" width=\"500\" height=\"98\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/RegularError.png 606w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/RegularError-300x59.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<h5>The Concept <span style=\"font-family: courier new, courier;\">regular<\/span><\/h5>\n<p>The C++20 concept regular (line 7) uses a more elaborate implementation. Consequentially, I got a more elaborated error message.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5839\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularCpp20Error.png\" alt=\"regularCpp20Error\" width=\"650\" height=\"137\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularCpp20Error.png 1101w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularCpp20Error-300x63.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularCpp20Error-1024x216.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularCpp20Error-768x162.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<h4>MSVC<\/h4>\n<p>The error message of the window&#8217;s compiler is too unspecific.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5840\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularWin.PNG\" alt=\"regularWin\" width=\"600\" height=\"121\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularWin.PNG 3556w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularWin-300x60.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularWin-1024x206.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularWin-768x155.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularWin-1536x310.png 1536w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/01\/regularWin-2048x413.png 2048w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Now I&#8217;m done with my miniseries on concepts in C++20, I&#8217;m curious to know your opinion on concepts. <strong>Are concepts an evolution or a revolution in C++?<\/strong> I&#8217;ll be happy if you drop me an E-Mail, including Thursday (06.02). I will use my <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-concepts-an-evolution-or-a-revolution-in-c\">next final post<\/a> to concepts to present your opinions. When I should mention your name, say it explicitly.&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<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&nbsp;int&#8220;. Formally, your concrete type should be regular. In this post, I define the concepts&nbsp;Regular&nbsp;and&nbsp;SemiRegular.<\/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-5841","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\/5841","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=5841"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5841\/revisions"}],"predecessor-version":[{"id":6757,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5841\/revisions\/6757"}],"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=5841"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5841"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5841"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}