{"id":4985,"date":"2016-10-15T22:00:18","date_gmt":"2016-10-15T22:00:18","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/more-and-more-save\/"},"modified":"2023-06-26T12:39:14","modified_gmt":"2023-06-26T12:39:14","slug":"more-and-more-save","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/more-and-more-save\/","title":{"rendered":"More and More Save"},"content":{"rendered":"<p>In the post <a href=\"https:\/\/www.modernescpp.com\/index.php\/statically-checked\">Statically checked <\/a>I wrote that the functions of the type-traits library are an ideal fit for <span style=\"font-family: courier new,courier;\">static_assert.<\/span> The reason is that <span style=\"font-family: courier new,courier;\">static_assert<\/span> requires a constant expression. The functions of the type-traits library provide a lot of&nbsp;checks which can be performed at compile time. With these posts, I will prove my statement.<\/p>\n<p><!--more--><\/p>\n<h2>gcd &#8211; The first<\/h2>\n<p>Before I describe&nbsp;systematically the functionality of the type-traits library I will start in this post with an example. My starting point is the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Greatest_common_divisor\">Euclid algorithm<\/a> to calculate the greatest common divisor of two numbers.<\/p>\n<p>It&#8217;s quite easy to implement the algorithm as a function template and feed it with various arguments.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ gcd.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\nT gcd(T a, T b){\r\n  <span style=\"color: #0000ff;\">if<\/span>( b == 0 ){ <span style=\"color: #0000ff;\">return<\/span> a; }\r\n  <span style=\"color: #0000ff;\">else<\/span>{\r\n    <span style=\"color: #0000ff;\">return<\/span> gcd(b, a % b);\r\n  }\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(100,10)= \"<\/span> &lt;&lt;  gcd(100,10)  &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(100,33)= \"<\/span> &lt;&lt; gcd(100,33) &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(100,0)= \"<\/span> &lt;&lt; gcd(100,0)  &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; gcd(3.5,4.0)&lt;&lt; std::endl;\r\n  std::cout &lt;&lt; gcd(<span style=\"color: #a31515;\">\"100\"<\/span>,<span style=\"color: #a31515;\">\"10\"<\/span>) &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; gcd(100,10L) &lt;&lt; gcd(100,10L) &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>But the compilation of the program fails. The compiler tries in vain to instantiate the templates.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4980\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd.png\" alt=\"gcd\" width=\"800\" height=\"553\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd.png 867w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd-300x207.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd-768x531.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/p>\n<p>The function template has two serious issues. First, it is too generic. So the function template accepts <span style=\"font-family: courier new,courier;\">doubles<\/span> (line 21) and C strings (line 22). But it makes no sense to determine the greatest common divisor of both data types. The modulo operation for the <span style=\"font-family: courier new,courier;\">double<\/span> and the C string values fails in line 9. But that&#8217;s not the only issue. Second, <span style=\"font-family: courier new,courier;\">gcd<\/span> depend on one type parameter <span style=\"font-family: courier new,courier;\">T.<\/span> This shows the function template signature <span style=\"font-family: courier new,courier;\">gcd(T a, T b)<\/span>). <span style=\"font-family: courier new,courier;\">a<\/span> and <span style=\"font-family: courier new,courier;\">b<\/span> have to be of the same type <span style=\"font-family: courier new,courier;\">T.<\/span> There is no conversion for type parameters. Therefore, the instantiation of <span style=\"font-family: courier new,courier;\">gcd<\/span> with an <span style=\"font-family: courier new,courier;\">int<\/span> type and a <span style=\"font-family: courier new,courier;\">long<\/span> type (line 24) fails.&nbsp; <span style=\"font-family: courier new,courier;\"><\/span><span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<p>Thanks to the type-traits library the first issue is quickly solved. The second issue requires much more effort.<\/p>\n<\/p>\n<h2>gcd &#8211; The second<\/h2>\n<p>I ignore for simplicity reasons in the rest of the post that both arguments have to be positive numbers. But back to the first issue. The <span style=\"font-family: courier new,courier;\">static_assert<\/span> operator and the predicate <span style=\"font-family: courier new,courier;\">std::is_integral&lt;T&gt;::value<\/span> helps me to check at compile time<span style=\"font-family: courier new,courier;\"> <\/span>whether<span style=\"font-family: courier new,courier;\"> T<\/span> is an integral type. A predicate&nbsp;always returns a boolean value.&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ gcd_2.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;type_traits&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\nT gcd(T a, T b){\r\n  static_assert(std::is_integral&lt;T&gt;::value, <span style=\"color: #a31515;\">\"T should be an integral type!\"<\/span>);\r\n  <span style=\"color: #0000ff;\">if<\/span>( b == 0 ){ <span style=\"color: #0000ff;\">return<\/span> a; }\r\n  <span style=\"color: #0000ff;\">else<\/span>{\r\n    <span style=\"color: #0000ff;\">return<\/span> gcd(b, a % b);\r\n  }\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; gcd(3.5,4.0)&lt;&lt; std::endl;\r\n  std::cout &lt;&lt; gcd(<span style=\"color: #a31515;\">\"100\"<\/span>,<span style=\"color: #a31515;\">\"10\"<\/span>) &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Great. I have solved the first issue of the gcd algorithm. The compilation will not&nbsp;fail by accident because the modulo operator is not defined for a <span style=\"font-family: courier new,courier;\">double<\/span> value and a C string. The compilation fails because the assertion in line 8 will not hold true. The subtle difference is that I now get an exact error message and not a cryptic output of a failed template instantiation as in the first example.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4981\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_2.png\" alt=\"gcd 2\" width=\"800\" height=\"334\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_2.png 883w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_2-300x125.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_2-768x321.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/p>\n<p>The rule is quite simple. <strong>A compilation has to fail and I should get an unambiguous error message. <\/strong><\/p>\n<p>But what&#8217;s about the second issue. The gcd algorithm should accept arguments of a different type.<\/p>\n<h2>gcd &#8211; The third<\/h2>\n<p>&nbsp;That no big deal. But stop. What is the type of the result?&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T1, <span style=\"color: #0000ff;\">typename<\/span> T2&gt;\r\n??? gcd(T1 a, T2 b){\r\n  static_assert(std::is_integral&lt;T1&gt;::value, <span style=\"color: #a31515;\">\"T1 should be an integral type!\"<\/span>);\r\n  static_assert(std::is_integral&lt;T2&gt;::value, <span style=\"color: #a31515;\">\"T2 should be an integral type!\"<\/span>);\r\n  <span style=\"color: #0000ff;\">if<\/span>( b == 0 ){ <span style=\"color: #0000ff;\">return<\/span> a; }\r\n  <span style=\"color: #0000ff;\">else<\/span>{\r\n    <span style=\"color: #0000ff;\">return<\/span> gcd(b, a % b);\r\n  }\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The three questions marks in line 2 show the core of the issue. Should the first type or the second type be the return type of the algorithm? Or should the algorithm derive a new type from the two arguments? The type-traits library comes to my rescue. I will present two variations.<\/p>\n<p>&nbsp;<\/p>\n<h3>The smaller type<\/h3>\n<p>A good choice for the return type is to use the smaller of both types. Therefore, I need a ternary operator at compile time. Thanks to the type-traits library we have. The ternary function <span style=\"font-family: courier new,courier;\">std::conditional<\/span> operates on types and not on values. That&#8217;s because we apply the function at compile time. So we have to feed <span style=\"font-family: courier new,courier;\">std::conditional<\/span> with the right constant expression and we are done. <span style=\"font-family: courier new,courier;\">std::conditional&lt;(sizeof(T1) &lt; sizeof(T2)), T1, T2&gt;::type<\/span> will return at compile time <span style=\"font-family: courier new,courier;\">T1<\/span> if <span style=\"font-family: courier new,courier;\">T1<\/span> is smaller than <span style=\"font-family: courier new,courier;\">T2<\/span>; it will return <span style=\"font-family: courier new,courier;\">T2<\/span> if <span style=\"font-family: courier new,courier;\">T1<\/span> is not smaller than&nbsp;<span style=\"font-family: courier new,courier;\">T1<\/span>.&nbsp;<\/p>\n<p>Let&#8217;s apply the logic. <\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ gcd_3_smaller.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;type_traits&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;typeinfo&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T1, <span style=\"color: #0000ff;\">typename<\/span> T2&gt;\r\n<span style=\"color: #0000ff;\">typename<\/span> std::conditional &lt;(<span style=\"color: #0000ff;\">sizeof<\/span>(T1) &lt; <span style=\"color: #0000ff;\">sizeof<\/span>(T2)), T1, T2&gt;::type gcd(T1 a, T2 b){\r\n  static_assert(std::is_integral&lt;T1&gt;::value, <span style=\"color: #a31515;\">\"T1 should be an integral type!\"<\/span>);\r\n  static_assert(std::is_integral&lt;T2&gt;::value, <span style=\"color: #a31515;\">\"T2 should be an integral type!\"<\/span>);\r\n  <span style=\"color: #0000ff;\">if<\/span>( b == 0 ){ <span style=\"color: #0000ff;\">return<\/span> a; }\r\n  <span style=\"color: #0000ff;\">else<\/span>{\r\n    <span style=\"color: #0000ff;\">return<\/span> gcd(b, a % b);\r\n  }\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(100,10)= \"<\/span> &lt;&lt;  gcd(100,10)  &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(100,33)= \"<\/span> &lt;&lt; gcd(100,33) &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(100,0)= \"<\/span> &lt;&lt; gcd(100,0)  &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(100,10LL)= \"<\/span> &lt;&lt; gcd(100,10LL) &lt;&lt; std::endl;\r\n\r\n  std::conditional &lt;(<span style=\"color: #0000ff;\">sizeof<\/span>(100) &lt; <span style=\"color: #0000ff;\">sizeof<\/span>(10LL)), <span style=\"color: #2b91af;\">long<\/span> <span style=\"color: #2b91af;\">long<\/span>, <span style=\"color: #2b91af;\">long<\/span>&gt;::type uglyRes= gcd(100,10LL);\r\n  <span style=\"color: #0000ff;\">auto<\/span> res= gcd(100,10LL);\r\n  <span style=\"color: #0000ff;\">auto<\/span> res2= gcd(100LL,10L);\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"typeid(gcd(100,10LL)).name(): \"<\/span> &lt;&lt; <span style=\"color: #0000ff;\">typeid<\/span>(res).name() &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"typeid(gcd(100LL,10L)).name(): \"<\/span> &lt;&lt; <span style=\"color: #0000ff;\">typeid<\/span>(res2).name() &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The key line of the program is the line 8 with the return type of the <span style=\"font-family: courier new,courier;\">gcd<\/span> algorithm. Of course, the algorithm can also deal with templates arguments of the same type. You can observe it in line 21 to 24 and the output of the program. But what&#8217;s about line 27? I use the number 100 of type <span style=\"font-family: courier new,courier;\">int<\/span> and the number 10 of type <span style=\"font-family: courier new,courier;\">long long int. T<\/span>he result for the greatest common divisor is 10. The line 29 is extremely ugly. I have to repeat the expression <span style=\"font-family: courier new,courier;\">std::conditional &lt;(sizeof(100) &lt; sizeof(10LL)), long long, long&gt;::type<\/span> to determine the right type of the variable <span style=\"font-family: courier new,courier;\">uglyRes.<\/span><span style=\"font-family: courier new,courier;\"> <\/span>Automatic type deduction with<span style=\"font-family: courier new,courier;\"> <span style=\"font-family: courier new,courier;\">auto<\/span> <\/span>comes to my rescue (line 30 and 31). The <span style=\"font-family: courier new,courier;\">typeid<\/span> operator in line 33 and 34 shows that the result type of the arguments of type <span style=\"font-family: courier new,courier;\">int<\/span> and <span style=\"font-family: courier new,courier;\">long long int<\/span> is <strong><span style=\"font-family: courier new,courier;\">int<\/span><\/strong><span style=\"font-family: courier new,courier;\">;<\/span> that the result type of the types <span style=\"font-family: courier new,courier;\">long long int<\/span> and <span style=\"font-family: courier new,courier;\">long int<\/span> is <strong><span style=\"font-family: courier new,courier;\">long int<\/span><\/strong>. &nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4982\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_3_smaller.png\" alt=\"gcd 3 smaller\" width=\"407\" height=\"274\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_3_smaller.png 407w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_3_smaller-300x202.png 300w\" sizes=\"auto, (max-width: 407px) 100vw, 407px\" \/><\/p>\n<h3>The common type<\/h3>\n<p>Now to my second variation. Often it is not necessary to determine the smaller type at compile time but to determine that type to which all types can implicitly be converted to. That&#8217;s the job of the function template <span style=\"font-family: courier new,courier;\">std::common_type<\/span> from the &#8211; of course you know it already &#8211; type-traits library. <span style=\"font-family: courier new,courier;\">std::common_type<\/span> can handle an arbitrary number of template arguments. To say it more formally. <span style=\"font-family: courier new,courier;\">std::common_type<\/span> is a <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/parameter_pack\">variadic template. <\/a><\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ gcd_3_common.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;type_traits&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;typeinfo&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T1, <span style=\"color: #0000ff;\">typename<\/span> T2&gt;\r\n<span style=\"color: #0000ff;\">typename<\/span> std::common_type&lt;T1, T2&gt;::type gcd(T1 a, T2 b){\r\n  static_assert(std::is_integral&lt;T1&gt;::value, <span style=\"color: #a31515;\">\"T1 should be an integral type!\"<\/span>);\r\n  static_assert(std::is_integral&lt;T2&gt;::value, <span style=\"color: #a31515;\">\"T2 should be an integral type!\"<\/span>);\r\n  <span style=\"color: #0000ff;\">if<\/span>( b == 0 ){ <span style=\"color: #0000ff;\">return<\/span> a; }\r\n  <span style=\"color: #0000ff;\">else<\/span>{\r\n    <span style=\"color: #0000ff;\">return<\/span> gcd(b, a % b);\r\n  }\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"typeid(gcd(100,10)).name(): \"<\/span> &lt;&lt; <span style=\"color: #0000ff;\">typeid<\/span>(gcd(100,10)).name() &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"typeid(gcd(100,10L)).name(): \"<\/span> &lt;&lt; <span style=\"color: #0000ff;\">typeid<\/span>(gcd(100,10L)).name() &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"typeid(gcd(100,10LL)).name(): \"<\/span> &lt;&lt; <span style=\"color: #0000ff;\">typeid<\/span>(gcd(100,10LL)).name() &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The only difference to the last implementation is that <span style=\"font-family: courier new,courier;\">std::common_type<\/span> in line 8 determines the return type. I ignore in this example the results of the gcd because I&#8217;m more interested in the types of the results. With the argument types <span style=\"font-family: courier new,courier;\">int<\/span> and<span style=\"font-family: courier new,courier;\"> int int<\/span> I get <strong><span style=\"font-family: courier new,courier;\">int<\/span><\/strong>; with the argument types <span style=\"font-family: courier new,courier;\">int<\/span> and <span style=\"font-family: courier new,courier;\">long int <strong>long int<\/strong><\/span>; with <span style=\"font-family: courier new,courier;\">int<\/span> and <span style=\"font-family: courier new,courier;\">long long int <strong>long long int<\/strong><\/span>.<\/p>\n<p><span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4983\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_3_common.png\" alt=\"gcd 3 common\" width=\"741\" height=\"209\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_3_common.png 741w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_3_common-300x85.png 300w\" sizes=\"auto, (max-width: 741px) 100vw, 741px\" \/><\/p>\n<h2>gcd &#8211; The fourth<\/h2>\n<p>But that&#8217;s not all. <span style=\"font-family: courier new,courier;\">std::enable_if<\/span> from the type-traits library also provides a very interesting variation. The previous implementations have in common that they will check in the function body If the arguments are integral types. The key observation is that the compiler always tries to instantiate the function temples and fails sometimes. You know the result. If the expression <span style=\"font-family: courier new,courier;\">std::integral<\/span> returns fall, the instantiation will fail. That is not the best way. It would be better if the function template is only available for the valid types. Therefore, I put the check of the function template from the template body to the template signature.<\/p>\n<p>I order to concentrate on the essentials, I used the same type for the function arguments. Therefore, the return type is obvious.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ gcd_4.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;type_traits&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T,\r\n         <span style=\"color: #0000ff;\">typename<\/span> std::enable_if&lt;std::is_integral&lt;T&gt;::value,T&gt;::type= 0&gt;       \r\nT gcd(T a, T b){\r\n  <span style=\"color: #0000ff;\">if<\/span>( b == 0 ){ <span style=\"color: #0000ff;\">return<\/span> a; }\r\n  <span style=\"color: #0000ff;\">else<\/span>{\r\n    <span style=\"color: #0000ff;\">return<\/span> gcd(b, a % b);\r\n  }\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(100,10)= \"<\/span> &lt;&lt;  gcd(100,10)  &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"gcd(3.5,4)= \"<\/span> &lt;&lt; gcd(3.5,4.0) &lt;&lt; std::endl;     \r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Line 7 is the critical line of the new program. The expression <span style=\"font-family: courier new,courier;\">std::is_integral<\/span> determines whether the type parameter T is integral. If T is not integral and, therefore, the return value <span style=\"font-family: courier new,courier;\">false<\/span>, I will not get a template instantiation. This is the decisive observation.<\/p>\n<p>If <span style=\"font-family: courier new,courier;\">std::enable_if<\/span> returns <span style=\"font-family: courier new,courier;\">true<\/span> as the first parameter, <span style=\"font-family: courier new,courier;\">std::enable_if<\/span> will have a <span style=\"font-family: courier new,courier;\">public member<\/span> <span style=\"font-family: courier new,courier;\">typedef<\/span> <span style=\"font-family: courier new,courier;\">type.<\/span> This type is used in line 7.&nbsp;If <span style=\"font-family: courier new,courier;\">std::enable_if<\/span> returns <span style=\"font-family: courier new,courier;\">false<\/span> as the first parameter, <span style=\"font-family: courier new,courier;\">std::enable_if<\/span> will have no public member typedef <span style=\"font-family: courier new,courier;\">type. <\/span>Therefore line 7 is not valid. But this is not an error. Only the template for precisely this type will not be instantiated. <span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<p>The rule in C++ says:&nbsp;When substituting the deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error. There is a shorter acronym for this rule <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/sfinae\">SFINAE<\/a> (<strong>S<\/strong>ubstitution<strong> F<\/strong>ailure <strong>I<\/strong>s <strong>N<\/strong>ot <strong>A<\/strong>n <strong>E<\/strong>rror).<\/p>\n<p>The output of the compilation shows it. There is no template specialization for the type <span style=\"font-family: courier new,courier;\">double.<\/span>&nbsp;<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4984\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_4.png\" alt=\"gcd 4\" width=\"800\" height=\"247\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_4.png 1064w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_4-300x93.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_4-1024x317.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/10\/gcd_4-768x237.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/p>\n<h2><span id=\"Explanation\" class=\"mw-headline\">What&#8217;s next?<\/span><\/h2>\n<p>The next post about the type-traits library will be systematic. The type-traits library has a lot of functions. They enable you to check, compare, and modify types at compile time. I will answer the two questions in the <a href=\"https:\/\/www.modernescpp.com\/index.php\/check-types\">next post<\/a>. How does it work? And. Which functions are available?<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the post Statically checked I wrote that the functions of the type-traits library are an ideal fit for static_assert. The reason is that static_assert requires a constant expression. The functions of the type-traits library provide a lot of&nbsp;checks which can be performed at compile time. With these posts, I will prove my statement.<\/p>\n","protected":false},"author":21,"featured_media":4980,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[364],"tags":[518,419],"class_list":["post-4985","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-embedded","tag-static_assert","tag-type-traits"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4985","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=4985"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4985\/revisions"}],"predecessor-version":[{"id":6936,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4985\/revisions\/6936"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/4980"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=4985"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=4985"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=4985"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}