{"id":5561,"date":"2018-11-22T18:27:19","date_gmt":"2018-11-22T18:27:19","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-regular-and-semiregular-typs\/"},"modified":"2023-06-26T10:18:30","modified_gmt":"2023-06-26T10:18:30","slug":"c-core-guidelines-regular-and-semiregular-typs","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-regular-and-semiregular-typs\/","title":{"rendered":"C++ Core Guidelines: Regular and SemiRegular Types"},"content":{"rendered":"<p>The topic for today is quite important when you create your type:&nbsp;<span style=\"font-family: courier new, courier;\">Regular<\/span> and <span style=\"font-family: courier new, courier;\">SemiRegular <\/span>types.<code class=\"highlighter-rouge no-highlight\"><br \/><\/code><\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5557\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/banner-1183445_1280.jpg\" alt=\"banner 1183445 1280\" width=\"600\" height=\"180\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/banner-1183445_1280.jpg 1280w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/banner-1183445_1280-300x90.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/banner-1183445_1280-1024x307.jpg 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/banner-1183445_1280-768x230.jpg 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Here is the exact rule for today.<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-regular\">T.46: Require template arguments to be at least <code class=\"highlighter-rouge no-highlight\">Regular<\/code> or <code class=\"highlighter-rouge no-highlight\">SemiRegular<\/code><\/a><\/h2>\n<p>Okay, the first question I have to answer is quite obvious. What is a <span style=\"font-family: courier new, courier;\">Regular<\/span> or a <span style=\"font-family: courier new, courier;\">SemiRegular<\/span> type? My answer is based on the proposal <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2018\/p0898r3.pdf\">p0898<\/a>.&nbsp;I assume you may already guess it. <span style=\"font-family: courier new, courier;\">Regular<\/span> and <span style=\"font-family: courier new, courier;\">SemiRegular<\/span> are concepts that are defined by concepts.<\/p>\n<h3><span style=\"font-family: courier new, courier;\">Regular<\/span><\/h3>\n<ul>\n<li><span style=\"font-family: courier new, courier;\">DefaultConstructible<\/span><\/li>\n<li><span style=\"font-family: courier new, courier;\">CopyConstructible, CopyAssignable<\/span><\/li>\n<li><span style=\"font-family: courier new, courier;\">MoveConstructible, MoveAssignable<\/span><\/li>\n<li><span style=\"font-family: courier new, courier;\">Destructible<\/span><\/li>\n<li><span style=\"font-family: courier new, courier;\">Swappable<\/span><\/li>\n<li><span style=\"font-family: courier new, courier;\">EqualityComparable<\/span><\/li>\n<\/ul>\n<h3><span style=\"font-family: courier new, courier;\">SemiRegular<\/span><\/h3>\n<ul>\n<li><span style=\"font-family: courier new, courier;\">Regular &#8211; EqualityComparable<\/span><\/li>\n<\/ul>\n<p>The term <span style=\"font-family: courier new, courier;\"><strong>Regular<\/strong><\/span> goes back to the father of the Standard Template Library <a href=\"https:\/\/en.wikipedia.org\/wiki\/Alexander_Stepanov\">Alexander Stepanov<\/a>. He introduced the term in his book Fundamentals of Generic Programming. Here is a&nbsp;<a href=\"http:\/\/stepanovpapers.com\/DeSt98.pdf\">short excerpt<\/a>. It&#8217;s quite easy to remember the eight concepts used to define a regular type. There is a well-known <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors-assignments-and-desctructors\">rule of six<\/a>:<\/p>\n<ul>\n<li>Default constructor:<span style=\"font-family: courier new, courier;\"> <code class=\"highlighter-rouge no-highlight\">X()<\/code><\/span><\/li>\n<li>Copy constructor: <code class=\"highlighter-rouge no-highlight\"><span style=\"font-family: courier new, courier;\">X(const X&amp;<\/span>)<\/code><\/li>\n<li>Copy assignment: <span style=\"font-family: courier new, courier;\"><code class=\"highlighter-rouge no-highlight\">operator=(const X&amp;)<\/code><\/span><\/li>\n<li>Move constructor: <span style=\"font-family: courier new, courier;\"><code class=\"highlighter-rouge no-highlight\">X(X&amp;&amp;)<\/code><\/span><\/li>\n<li>Move assignment: <code class=\"highlighter-rouge no-highlight\"><span style=\"font-family: courier new, courier;\">operator=(X&amp;&amp;)<\/span><\/code><\/li>\n<li>Destructor: <span style=\"font-family: courier new, courier;\"><code class=\"highlighter-rouge no-highlight\">~X()<\/code><\/span><\/li>\n<\/ul>\n<p>Just add the <span style=\"font-family: courier new, courier;\">Swappable<\/span> and <span style=\"font-family: courier new, courier;\">EqualityComparable<\/span> concepts to it. There is a more informal way to say that a type<span style=\"font-family: courier new, courier;\"> T<\/span> is regular: <span style=\"font-family: courier new, courier;\">T<\/span> behaves like an <span style=\"font-family: courier new, courier;\">int<\/span>.&nbsp;<\/p>\n<p>To get <strong><span style=\"font-family: courier new, courier;\">SemiRegular<\/span><\/strong>, you have to subtract <span style=\"font-family: courier new, courier;\">EqualityComparable<\/span> from <span style=\"font-family: courier new, courier;\">Regular<\/span>.<\/p>\n<p>I hear your next question: Why should our template arguments at least be&nbsp;<span style=\"font-family: courier new, courier;\">Regular<\/span> or <span style=\"font-family: courier new, courier;\">SemiRegular <\/span>or do as the <span style=\"font-family: courier new, courier;\">ints<\/span> do? <strong>The STL containers and algorithms, in particular, assume <span style=\"font-family: courier new, courier;\">Regular<\/span> data types.<\/strong><span style=\"font-family: courier new, courier;\"> <\/span><\/p>\n<p>What is commonly used but not a Regular type? Right: a reference.<\/p>\n<h3>References are not <span style=\"font-family: courier new, courier;\">Regular<\/span><\/h3>\n<p>Thanks to the<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\"> type-traits library<\/a>, the following program checks at compile time if <span style=\"font-family: courier new, courier;\">int&amp;<\/span> is a <span style=\"font-family: courier new, courier;\">SemiRegular<\/span> type.<\/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;\">\/\/ semiRegular.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;type_traits&gt;<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\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;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"std::is_default_constructible&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_default_constructible<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"std::is_copy_constructible&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_copy_constructible<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"std::is_copy_assignable&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_copy_assignable<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"std::is_move_constructible&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_move_constructible<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"std::is_move_assignable&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_move_assignable<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"std::is_destructible&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_destructible<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"std::is_swappable&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_swappable<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;        <span style=\"color: #0099ff; font-style: italic;\">\/\/ requires C++17<\/span>\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>First of all. The function<span style=\"font-family: courier new, courier;\"> std::is_swappable<\/span> requires C++17. Second, here is the output.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5558\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/semiRegular.png\" alt=\"semiRegular\" width=\"500\" height=\"273\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/semiRegular.png 895w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/semiRegular-300x163.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/semiRegular-768x418.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>You see a reference such as <span style=\"font-family: courier new, courier;\">int<\/span>&amp; is not default constructible. The output shows that a reference is not <span style=\"font-family: courier new, courier;\">SemiRegular<\/span> and, therefore, not <span style=\"font-family: courier new, courier;\">Regular.<\/span> To check if a type is <span style=\"font-family: courier new, courier;\">Regular<\/span> at compile-time, I need a function <span style=\"font-family: courier new, courier;\">isEqualityComparable<\/span> which is not part of the type-traits library. Let&#8217;s do it by myself.<\/p>\n<\/p>\n<h4>isEqualityComparable<\/h4>\n<p>In C++20, we might get the <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/experimental\/is_detected\">detection idiom<\/a> which is part of the <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html\">library fundamental TS v2<\/a>. Now, it&#8217;s a piece of cake to implement<span style=\"font-family: courier new, courier;\"> isEqualityComparable<\/span>.<\/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;\">\/\/ equalityComparable.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;experimental\/type_traits&gt;                                                       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span><\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&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;\">using<\/span> <span style=\"color: #007788; font-weight: bold;\">equal_comparable_t<\/span> <span style=\"color: #555555;\">=<\/span> decltype(std<span style=\"color: #555555;\">::<\/span>declval<span style=\"color: #555555;\">&lt;<\/span>T&amp;<span style=\"color: #555555;\">&gt;<\/span>() <span style=\"color: #555555;\">==<\/span> std<span style=\"color: #555555;\">::<\/span>declval<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\"><\/span>T&amp;<span style=\"color: #555555;\">&gt;<\/span>());           <span style=\"color: #009999;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span><\/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> isEqualityComparable<span style=\"color: #555555;\">:<\/span> \r\n       std<span style=\"color: #555555;\">::<\/span>experimental<span style=\"color: #555555;\">::<\/span>is_detected<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">equal_comparable_t<\/span>, T<span style=\"color: #555555;\">&gt;<\/span>{};                           <span style=\"color: #009999;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span><\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> EqualityComparable { };                                                            <span style=\"color: #009999;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span><\/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: #009999;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span><\/span>\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n    \r\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;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"isEqualityComparable&lt;EqualityComparable&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> \r\n                  isEqualityComparable<span style=\"color: #555555;\">&lt;<\/span>EqualityComparable<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n                  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"isEqualityComparable&lt;NotEqualityComparable&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> \r\n                  isEqualityComparable<span style=\"color: #555555;\">&lt;<\/span>NotEqualityComparable<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The new feature is in the <span style=\"font-family: courier new, courier;\">experimental<\/span> namespace (1). Line (3) is the crucial one. It detects if the expression (2) is valid for type T.&nbsp; The type-trait <span style=\"font-family: courier new, courier;\">isEqualityComparable<\/span> works for an <span style=\"font-family: courier new, courier;\">EqualityComparable<\/span> (4) and a <span style=\"font-family: courier new, courier;\">NotEqualityComparable<\/span>&nbsp;(5) type. Only <span style=\"font-family: courier new, courier;\">EqualityCompable<\/span> returns <span style=\"font-family: courier new, courier;\">true<\/span> because I overloaded the Equal-Comparison Operator.<\/p>\n<p>To compile the program, you need a new C++ compiler, such as GCC 8.2.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5559\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/equalityComparable.png\" alt=\"equalityComparable\" width=\"600\" height=\"283\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/equalityComparable.png 1305w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/equalityComparable-300x141.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/equalityComparable-1024x483.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/equalityComparable-768x362.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Until C++20, comparison operators are automatically generated for arithmetic types, enumerations, and with restrictions for pointers. This may change with C++20 due to the <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/default_comparisons\">spaceship operator<\/a>: <span style=\"font-family: courier new, courier;\">&lt;=&gt;.<\/span>&nbsp; With C++20, when a class defines <span class=\"t-c\"><span class=\"mw-geshi cpp source-cpp\">operator <span class=\"sy1\" style=\"font-family: courier new, courier;\">&lt;=&gt;,<\/span><\/span><\/span> automatically the operators&nbsp;<span style=\"font-family: courier new, courier;\"> ==,&nbsp;!=, &lt;, &lt;=, &gt;, <\/span>and<span style=\"font-family: courier new, courier;\"> &gt;=&nbsp;<\/span>are generated. It&#8217;s possible to define operator <span style=\"font-family: courier new, courier;\">&lt;=&gt;<\/span> as defaulted, such as for the type <span style=\"font-family: courier new, courier;\">Point.<\/span><\/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: #00aa88; font-weight: bold;\">Point<\/span> {\r\n   <span style=\"color: #007788; font-weight: bold;\">int<\/span> x;\r\n   <span style=\"color: #007788; font-weight: bold;\">int<\/span> y;\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\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> Point<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>;\r\n   ....\r\n};\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ compiler generates all six relational operators<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In this case, the compiler will generate the implementation. The default operator&lt;=&gt; performs a lexicographical comparison on its bases (left-to-right, depth-first) and continues with its non-static member in declaration order. This comparison applies to&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Short-circuit_evaluation\">short-circuit evaluation<\/a>. This means evaluating a logical expression ends if the result is known.<\/p>\n<p>&nbsp;<\/p>\n<p>Now, I have all the ingredients to define <span style=\"font-family: courier new, courier;\">Regular<\/span> and <span style=\"font-family: courier new, courier;\">SemiRegular.<\/span> Here are my new type traits.<\/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;\">\/\/ isRegular.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;experimental\/type_traits&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&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;\">using<\/span> <span style=\"color: #007788; font-weight: bold;\">equal_comparable_t<\/span> <span style=\"color: #555555;\">=<\/span> decltype(std<span style=\"color: #555555;\">::<\/span>declval<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&amp;&gt;<\/span>() <span style=\"color: #555555;\">==<\/span> std<span style=\"color: #555555;\">::<\/span>declval<span style=\"color: #555555;\">&lt;<\/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;\">typename<\/span> T<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> isEqualityComparable<span style=\"color: #555555;\">:<\/span> \r\n       std<span style=\"color: #555555;\">::<\/span>experimental<span style=\"color: #555555;\">::<\/span>is_detected<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">equal_comparable_t<\/span>, T<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\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<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> isRegular<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                                         isSemiRegular<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                                         isEqualityComparable<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: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\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;\r\n                  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"isSemiRegular&lt;int&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> isSemiRegular<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"isRegular&lt;int&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> isRegular<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"isSemiRegular&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> isSemiRegular<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"isRegular&lt;int&amp;&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> isRegular<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The usage of the new type-traits <span style=\"font-family: courier new, courier;\">isSemiRegular<\/span> and <span style=\"font-family: courier new, courier;\">isRegular<\/span> makes the main program quite readable.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5560\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/isRegular.png\" alt=\"isRegular\" width=\"350\" height=\"227\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/isRegular.png 634w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/isRegular-300x194.png 300w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>With my<a href=\"http:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-argument-dependent-lookup-or-koenig-lookup\"> next post<\/a>, I jump directly to the template definition.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The topic for today is quite important when you create your type:&nbsp;Regular and SemiRegular types.<\/p>\n","protected":false},"author":21,"featured_media":5557,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[415,416],"class_list":["post-5561","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-concepts","tag-regular"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5561","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=5561"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5561\/revisions"}],"predecessor-version":[{"id":6803,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5561\/revisions\/6803"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5557"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5561"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5561"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5561"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}