{"id":5527,"date":"2018-10-12T04:48:59","date_gmt":"2018-10-12T04:48:59","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-the-definition-of-concepts\/"},"modified":"2023-06-26T11:43:41","modified_gmt":"2023-06-26T11:43:41","slug":"c-core-guidelines-rules-for-the-definition-of-concepts","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-the-definition-of-concepts\/","title":{"rendered":"C++ Core Guidelines: Rules for the Definition of Concepts"},"content":{"rendered":"<p>Although rule T.11 states: <a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-std-concepts\">Whenever possible, use standard concepts <\/a>you sometimes have to define your concepts. This post gives you rules to do it.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5525\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/definition-390785_1280.jpg\" alt=\"definition 390785 1280\" width=\"600\" height=\"407\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/definition-390785_1280.jpg 1280w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/definition-390785_1280-300x204.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/definition-390785_1280-1024x695.jpg 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/definition-390785_1280-768x521.jpg 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>The C++ core guidelines have nine rules for defining concepts. Seven of them have content. Here are the first four for today.<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-low\">T.20: Avoid \u201cconcepts\u201d without meaningful semantics<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-complete\">T.21: Require a complete set of operations for a concept<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-axiom\">T.22: Specify axioms for concepts<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-refine\">T.23: Differentiate a refined concept from its more general case by adding new use patterns<\/a><\/li>\n<\/ul>\n<p>Let&#8217;s see how to define concepts<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-low\">T.20: Avoid \u201cconcepts\u201d without meaningful semantics<\/a><\/h2>\n<p>This rule is quite obvious, but what does meaningful semantic mean? Meaningful semantics are not just simple constraints such as <code>has_plus<\/code> but concepts such as <code>Number,<\/code> <code>Range,<\/code> or <code>InputIterator.&nbsp;<\/code><\/p>\n<p>For example, the following concept <code>Addable<\/code> requires <code>has_plus<\/code> and is, therefore, also fulfilled by a string.<\/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;\">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 Addable <span style=\"color: #555555;\">=<\/span> has_plus<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>;    <span style=\"color: #0099ff; font-style: italic;\">\/\/ bad; insufficient<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>Addable N<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #006699; font-weight: bold;\">auto<\/span> algo(<span style=\"color: #006699; font-weight: bold;\">const<\/span> N<span style=\"color: #555555;\">&amp;<\/span> a, <span style=\"color: #006699; font-weight: bold;\">const<\/span> N<span style=\"color: #555555;\">&amp;<\/span> b) <span style=\"color: #0099ff; font-style: italic;\">\/\/ use two numbers<\/span>\r\n{\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> a <span style=\"color: #555555;\">+<\/span> b;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">7<\/span>;\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> y <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">9<\/span>;\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> z <span style=\"color: #555555;\">=<\/span> algo(x, y);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ z = 16<\/span>\r\n\r\nstring xx <span style=\"color: #555555;\">=<\/span> <span style=\"color: #cc3300;\">\"7\"<\/span>;\r\nstring yy <span style=\"color: #555555;\">=<\/span> <span style=\"color: #cc3300;\">\"9\"<\/span>;\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> zz <span style=\"color: #555555;\">=<\/span> algo(xx, yy);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ zz = \"79\"<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I assume this was not your intention because the function template <code>algo<\/code> should accept arguments that model numbers and not just <span style=\"font-family: 'courier new', courier;\">A<\/span><span style=\"font-family: 'courier new', courier;\">ddable<\/span>. The solution is quite simple. Define and use a concept <code>Number<\/code> with a meaningful semantic.<\/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: #0099ff; font-style: italic;\">\/\/ The operators +, -, *, and \/ for a number <\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ are assumed to follow the usual mathematical rules<\/span>\r\nconcept Number <span style=\"color: #555555;\">=<\/span> has_plus<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>\r\n                 <span style=\"color: #555555;\">&amp;&amp;<\/span> has_minus<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>\r\n                 <span style=\"color: #555555;\">&amp;&amp;<\/span> has_multiply<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>\r\n                 <span style=\"color: #555555;\">&amp;&amp;<\/span> has_divide<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>Number N<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #006699; font-weight: bold;\">auto<\/span> algo(<span style=\"color: #006699; font-weight: bold;\">const<\/span> N<span style=\"color: #555555;\">&amp;<\/span> a, <span style=\"color: #006699; font-weight: bold;\">const<\/span> N<span style=\"color: #555555;\">&amp;<\/span> b)\r\n{\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> a <span style=\"color: #555555;\">+<\/span> b;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Now the invocation of <code>algo<\/code> with a string would give an error. The next rule is a particular case of this rule.<\/p>\n<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-complete\">T.21: Require a complete set of operations for a concept<\/a><\/h2>\n<p>First of all, what is a complete set of operations? Here are two complete sets for <code>Arithmetic<\/code> and <code>Comparable.<\/code><\/p>\n<ul>\n<li><strong>Arithmetic:<\/strong><code> +, -, *, \/, +=, -=, *=, \/=<\/code><\/li>\n<li><strong>Comparable:<code> &lt;, &gt;, &lt;=, &gt;=, ==, !=<\/code><\/strong><\/li>\n<\/ul>\n<p>Do you want to know what the acronym POLA stands for? It stands for <a href=\"https:\/\/en.wikipedia.org\/wiki\/Principle_of_least_astonishment\"><strong>P<\/strong>rinciple <strong>O<\/strong>f<strong> L<\/strong>east <strong>A<\/strong>stonishment<\/a>. You can easily break this principle of good software design if you implement just a partial set of operations.<\/p>\n<p>Here is an auspicious example from the guidelines.&nbsp; The concept <code>Minimal<\/code> in this case, supports<code>==, &lt;<\/code> and&nbsp;<code>+.<\/code><\/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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">f<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> Minimal<span style=\"color: #555555;\">&amp;<\/span> x, <span style=\"color: #006699; font-weight: bold;\">const<\/span> Minimal<span style=\"color: #555555;\">&amp;<\/span> y)\r\n{\r\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (<span style=\"color: #555555;\">!<\/span>(x <span style=\"color: #555555;\">==<\/span> y)) { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }    <span style=\"color: #0099ff; font-style: italic;\">\/\/ OK<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (x <span style=\"color: #555555;\">!=<\/span> y) { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }       <span style=\"color: #0099ff; font-style: italic;\">\/\/ surprise! error<\/span>\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">while<\/span> (<span style=\"color: #555555;\">!<\/span>(x <span style=\"color: #555555;\">&lt;<\/span> y)) { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }  <span style=\"color: #0099ff; font-style: italic;\">\/\/ OK<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">while<\/span> (x <span style=\"color: #555555;\">&gt;=<\/span> y) { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }    <span style=\"color: #0099ff; font-style: italic;\">\/\/ surprise! error<\/span>\r\n\r\n    x <span style=\"color: #555555;\">=<\/span> x <span style=\"color: #555555;\">+<\/span> y;          <span style=\"color: #0099ff; font-style: italic;\">\/\/ OK<\/span>\r\n    x <span style=\"color: #555555;\">+=<\/span> y;             <span style=\"color: #0099ff; font-style: italic;\">\/\/ surprise! error<\/span>\r\n}\r\n<\/pre>\n<\/div>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-axiom\">T.22: Specify axioms for concepts<\/a><\/h2>\n<p>First of all: What is an axiom? Here is my definition from <a href=\"https:\/\/en.wikipedia.org\/wiki\/Axiom\">Wikipedia<\/a>:<\/p>\n<ul>\n<li>An <b>axiom<\/b> or <b>postulate<\/b> is a statement that is taken to be true, to serve as a premise or starting point for further reasoning and arguments.<\/li>\n<\/ul>\n<p>Because C++ does not support axioms, you must express them with comments. If C++ does support them in the future, you can remove the comment symbol<code> \/\/<\/code> in front of the axiom in the following example.<\/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: #0099ff; font-style: italic;\">\/\/ axiom(T a, T b) { a + b == b + a; a - a == 0; a * (b + c) == a * b + a * c; \/*...*\/ }<\/span>\r\n    concept Number <span style=\"color: #555555;\">=<\/span> requires(T a, T b) {\r\n        {a <span style=\"color: #555555;\">+<\/span> b} <span style=\"color: #555555;\">-&gt;<\/span> T;  \r\n        {a <span style=\"color: #555555;\">-<\/span> b} <span style=\"color: #555555;\">-&gt;<\/span> T;\r\n        {a <span style=\"color: #555555;\">*<\/span> b} <span style=\"color: #555555;\">-&gt;<\/span> T;\r\n        {a <span style=\"color: #555555;\">\/<\/span> b} <span style=\"color: #555555;\">-&gt;<\/span> T;\r\n    }\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The axiom means, in this case, that the number follows the mathematical rules. In contrast, the concept requires that a Number has to support the binary operations <code>+, -, *,<\/code> and <code>\/<\/code> and that the result is convertible to <code>T. T<\/code> is the type of argument.<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-refine\">T.23: Differentiate a refined concept from its more general case by adding new use patterns<\/a><\/h2>\n<p>If two concepts have the same requirements, they are logically equivalent. This means the compiler can&#8217;t distinguish them and may not automatically choose the correct one during overload resolution.<\/p>\n<p>To make the rule clear, here is a simplified version of the concept <code>BidirectionalIterator<\/code> and the refined concept <code>RandomAccessIterator.<br \/><\/code><\/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;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> I<span style=\"color: #555555;\">&gt;<\/span>\r\nconcept <span style=\"color: #007788; font-weight: bold;\">bool<\/span> BidirectionalIterator <span style=\"color: #555555;\">=<\/span> ForwardIterator<span style=\"color: #555555;\">&lt;<\/span>I<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<\/span> \r\n                                     requires(I iter){ \r\n                                         <span style=\"color: #555555;\">--<\/span>iter;  \r\n                                         iter<span style=\"color: #555555;\">--<\/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> I<span style=\"color: #555555;\">&gt;<\/span>\r\nconcept <span style=\"color: #007788; font-weight: bold;\">bool<\/span> RandomAccessIterator <span style=\"color: #555555;\">=<\/span> BidirectionalIterator<span style=\"color: #555555;\">&lt;<\/span>I<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #555555;\">&amp;&amp;<span style=\"color: #555555;\"><\/span><span style=\"color: #555555;\"><\/span><\/span> <br \/>                                    Integer&lt;N&gt; &amp;&amp;\r\n                                    requires(I iter, I iter2, N n<span style=\"color: #006699; font-weight: bold;\"><\/span>){\r\n                                        iter <span style=\"color: #555555;\">+=<\/span> n;               <span style=\"color: #0099ff; font-style: italic;\">\/\/ increment or decrement an iterator<\/span>\r\n                                        iter <span style=\"color: #555555;\">-=<\/span> n;\r\n                                        n <span style=\"color: #555555;\">+<\/span> iter;                <span style=\"color: #0099ff; font-style: italic;\">\/\/ return a temp iterator<\/span>\r\n                                        iter <span style=\"color: #555555;\">+<\/span> n;\r\n                                        iter <span style=\"color: #555555;\">-<\/span> n; \r\n                                        iter[n];                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ access the element<\/span><br \/>                                        iter1 - iter2;           <span style=\"color: #0099ff; font-style: italic;\">\/\/ subtract two iterators<\/span><br \/>                                        iter1 &lt; iter2;           <span style=\"color: #0099ff; font-style: italic;\">\/\/ compare two iterators <\/span><br \/>                                        iter1 &lt;= iter2;<br \/>                                        iter1 &gt; iter2;<br \/>                                        iter1 &gt;= iter2;\r\n                                    }\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/iterator\/advance\">std::advance<\/a>(i, n)<\/code> increments a given iterator i by n elements. Depending on the value of <code>n<\/code>, the iterator is <code><\/code>incremented or decremented. When the iterator <code>i<\/code> is bidirectional iterator<code>, std::advance<\/code> has to step <code>n<\/code> times one element forward or backward. But when the iterator i is a random access iterator, just <code>n<\/code> is added to the iterator.<\/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;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>BidirectionalIterator I<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> advance(I<span style=\"color: #555555;\">&amp;<\/span> iter, <span style=\"color: #007788; font-weight: bold;\">int<\/span> n){...}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>RandomAccessIterator I<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> advance(I<span style=\"color: #555555;\">&amp;<\/span> iter, <span style=\"color: #007788; font-weight: bold;\">int<\/span> n){...}\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>list<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> lst{<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>, <span style=\"color: #ff6600;\">6<\/span>, <span style=\"color: #ff6600;\">7<\/span>, <span style=\"color: #ff6600;\">8<\/span>, <span style=\"color: #ff6600;\">9<\/span>};\r\nstd<span style=\"color: #555555;\">::<\/span>list<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;::<\/span>iterator listIt <span style=\"color: #555555;\">=<\/span> lst.begin();\r\nstd<span style=\"color: #555555;\">::<\/span>advance(listIt, <span style=\"color: #ff6600;\">2<\/span>);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ BidirectionalIterator<\/span>\r\n\r\nstd<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> vec{<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>, <span style=\"color: #ff6600;\">6<\/span>, <span style=\"color: #ff6600;\">7<\/span>, <span style=\"color: #ff6600;\">8<\/span>, <span style=\"color: #ff6600;\">9<\/span>};\r\nstd<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>iterator vecIt <span style=\"color: #555555;\">=<\/span> vec.begin();\r\nstd<span style=\"color: #555555;\">::<\/span>advance(vecIt, <span style=\"color: #ff6600;\">2<\/span>);    <span style=\"color: #0099ff; font-style: italic;\">\/\/ RandomAccessIterator<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In the case of the <code>std::vector&lt;int&gt;, vec.begin()<\/code> returns a random access iterator and, therefore, the fast variant of <code>std::advance<\/code> is used.<\/p>\n<p>Each container of the STL creates an iterator specific to its structure. Here is the overview:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5526\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/IteratorCategories.png\" alt=\"IteratorCategories\" width=\"500\" height=\"302\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/IteratorCategories.png 990w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/IteratorCategories-300x181.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/10\/IteratorCategories-768x464.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p id=\"t24-use-tag-classes-or-traits-to-differentiate-concepts-that-differ-only-in-semantics\">Three rules to the definition of concepts are left. In particular, the following rule, &#8220;T.24: Use tag classes or traits to differentiate concepts that differ only in semantics.&#8221; sounds pretty attractive. Let&#8217;s see in the <a href=\"https:\/\/goo.gl\/XM5Q8P\">next post<\/a> what a tag class or traits class is.&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Although rule T.11 states: Whenever possible, use standard concepts you sometimes have to define your concepts. This post gives you rules to do it.<\/p>\n","protected":false},"author":21,"featured_media":5525,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[415],"class_list":["post-5527","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-concepts"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5527","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=5527"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5527\/revisions"}],"predecessor-version":[{"id":6810,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5527\/revisions\/6810"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5525"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5527"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5527"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5527"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}