{"id":5515,"date":"2018-09-18T22:46:16","date_gmt":"2018-09-18T22:46:16","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-the-usage-of-concepts\/"},"modified":"2023-06-26T11:44:38","modified_gmt":"2023-06-26T11:44:38","slug":"c-core-guidelines-rules-for-the-usage-of-concepts","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-the-usage-of-concepts\/","title":{"rendered":"C++ Core Guidelines: Better Specific or Generic?"},"content":{"rendered":"<p>Concepts revolutionize the way we think about and use generic programming. They didn&#8217;t make it in C++11 or C++17 but with C++20, we will get them with a high probability.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5511\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/roads-320371_1280.jpg\" alt=\"roads 320371 1280\" width=\"500\" height=\"375\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/roads-320371_1280.jpg 1280w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/roads-320371_1280-300x225.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/roads-320371_1280-1024x768.jpg 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/roads-320371_1280-768x576.jpg 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>Before I write about using concepts, I want to make a general remark.<\/p>\n<h2>Too Specific versus Too Generic<\/h2>\n<p>Until C++20 we have in C++ two diametral ways to think about functions or user-defined types (classes). Functions or classes can be defined on specific types or on generic types. In the second case, we call them function or class templates. What are the downsides of each way?<\/p>\n<h3>Too Specific<\/h3>\n<p>It&#8217;s quite a job to define a function or class for each specific type. To avoid that burden, type conversion often comes to our rescue but it is also part of the problem. Let&#8217;s see what I mean.<\/p>\n<h4>Narrowing Conversion<\/h4>\n<p>You have a function <code>getInt(int a)<\/code>&nbsp;that you can invoke with a <code>double<\/code>. Now, narrowing conversion takes place.<\/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;\">\/\/ narrowingConversion.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">needInt<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> i){\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"int: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\t\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\t\r\n\t<span style=\"color: #007788; font-weight: bold;\">double<\/span> d{<span style=\"color: #ff6600;\">1.234<\/span>};\r\n\tstd<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"double: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> d <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\t\r\n\tneedInt(d);\r\n\t\r\n\tstd<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\t\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I assume that is not the behavior you wanted. You started with a <code>double<\/code> and ended with an <code>int<\/code>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5512\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/narrowingConversion.PNG\" alt=\"narrowingConversion\" width=\"300\" height=\"139\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/narrowingConversion.PNG 734w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/narrowingConversion-300x139.png 300w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>But conversion works also the other way around.<\/p>\n<h4>Integral Promotion<\/h4>\n<p>You have a user-defined type <code>MyHouse<\/code><span style=\"font-family: Courier New, Courier, monospace;\">. <\/span>An instance of <code>MyHouse<\/code> can be constructed in two ways. When invoked without an argument (1), its attribute <code>family<\/code> is set to an empty string. This means the house is still empty.&nbsp; To easily check if the house is empty or full, I implemented a conversion operator to <code>bool <\/code>(2). Fine or? No!<\/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;\">\/\/ conversionOperator.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> MyHouse{\r\n    MyHouse() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">default<\/span>;                            <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n    MyHouse(<span style=\"color: #006699; font-weight: bold;\">const<\/span> std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&amp;<\/span> fam)<span style=\"color: #555555;\">:<\/span> family(fam){}\r\n\t\r\n    <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span>(){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">!<\/span>family.empty(); }      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)                         <\/span>\r\n\t\r\n    std<span style=\"color: #555555;\">::<\/span>string family <span style=\"color: #555555;\">=<\/span> <span style=\"color: #cc3300;\">\"\"<\/span>;\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">needInt<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> i){\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"int: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\t\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\t\r\n    MyHouse firstHouse;\r\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (<span style=\"color: #555555;\">!<\/span>firstHouse){                                        \r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"The firstHouse is still empty.\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    };\r\n\t\r\n    MyHouse secondHouse(<span style=\"color: #cc3300;\">\"grimm\"<\/span>);                               \r\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (secondHouse){\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Family grimm lives in secondHouse.\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    }\r\n\t\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\t\r\n    needInt(firstHouse);              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)                <\/span>\r\n    needInt(secondHouse);             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n\t\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\t\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Now, instances of <code>MyHouse<\/code> can be used when an <code>int<\/code> is required. Strange!&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5513\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/conversionOperator.PNG\" alt=\"conversionOperator\" width=\"300\" height=\"139\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/conversionOperator.PNG 935w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/conversionOperator-300x139.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/conversionOperator-768x356.png 768w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Due to the overloaded operator bool (2), instances of <code>MyHouse<\/code> can be used as an <code>int<\/code> and can, therefore, be used in arithmetic expressions: <code>auto res = MyHouse() + 5<\/code>. This was not my intention! Just for completeness. With C++11, you can declare conversion operators as <code>explicit<\/code>. Therefore implicit conversions are not allowed.<\/p>\n<p><strong>My firm belief is that because of convenience reasons, we need the entire magic of conversions in C\/C++ to deal with the fact that functions only accept specific arguments.<\/strong><\/p>\n<p>Are templates the cure? No!<\/p>\n<\/p>\n<h3>Too Generic<\/h3>\n<p>Generic functions or classes can be invoked with arbitrary values. If the values do not satisfy the requirements of the function or class, no problem. You will get a compile-time error. Fine!<\/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;\">\/\/ gcd.cpp<\/span>\r\n\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\nT gcd(T a, T b){\r\n  <span style=\"color: #006699; font-weight: bold;\">if<\/span>( b <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0<\/span> ){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> a; }\r\n  <span style=\"color: #006699; font-weight: bold;\">else<\/span>{\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> gcd(b, a <span style=\"color: #555555;\">%<\/span> b);\r\n  }\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main(){\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;\"><\/span><span style=\"color: #555555;\"><\/span>gcd(<span style=\"color: #ff6600;\">100<\/span>, <span style=\"color: #ff6600;\">10<\/span>)  <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> gcd(<span style=\"color: #ff6600;\">3.5<\/span>, <span style=\"color: #ff6600;\">4.0<\/span>)<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> gcd(<span style=\"color: #cc3300;\">\"100\"<\/span>, <span style=\"color: #cc3300;\">\"10\"<\/span>) <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>What is the problem with this error message?<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5514\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/genericGCD.PNG\" alt=\"genericGCD\" width=\"600\" height=\"326\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/genericGCD.PNG 1800w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/genericGCD-300x163.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/genericGCD-1024x558.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/genericGCD-768x418.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/genericGCD-1536x836.png 1536w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Of course, it is pretty long and quite challenging to understand, but my crucial concern is a different one. The compilation&nbsp;fails because neither <code>double<\/code> or the C-strings supports the % operator. This means the error is due to the failed template instantiation for <code>double <\/code>and C-string. This is too late and, therefore, really bad. No template instantiation for type <code>double<\/code> or C-strings should be possible. The requirements for the arguments should be part of the function declaration and not a side-effect of an erroneous template instantiation.<\/p>\n<p>Now concepts come to our rescue.<\/p>\n<h3>The Third Way<\/h3>\n<p>With concepts, we get something in between. We can define functions or classes that act on semantic categories with them. Meaning the arguments of functions or classes are either too specific or too generic but named sets of requirements such as <em><code>Integral<\/code><\/em>.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Sorry for this short post, but one week before my multithreading workshop at the CppCon, I had neither the time nor the resources (no connectivity in the national parks in Washington state) to write an entire post. My <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-the-usage-of-concepts-2\">next post<\/a> will be particular because I will write about the CppCon. Afterward, I continue my story about generics and, in particular, about concepts.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Concepts revolutionize the way we think about and use generic programming. They didn&#8217;t make it in C++11 or C++17 but with C++20, we will get them with a high probability.<\/p>\n","protected":false},"author":21,"featured_media":5511,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[415],"class_list":["post-5515","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\/5515","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=5515"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5515\/revisions"}],"predecessor-version":[{"id":6812,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5515\/revisions\/6812"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5511"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}