{"id":5615,"date":"2019-01-24T13:39:13","date_gmt":"2019-01-24T13:39:13","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-programming-at-compile-time-with-type-traits-ii\/"},"modified":"2023-06-26T10:15:22","modified_gmt":"2023-06-26T10:15:22","slug":"c-core-guidelines-programming-at-compile-time-with-type-traits-ii","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-programming-at-compile-time-with-type-traits-ii\/","title":{"rendered":"C++ Core Guidelines: Programming at Compile Time with Type-Traits (The Second)"},"content":{"rendered":"<p>The type-traits library supports type checks, type comparisons, and type modifications at compile time. Right! Today, I write about type modifications at compile time.<\/p>\n<p><!--more--><\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5613\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/01\/TypeTraits.PNG\" alt=\"TypeTraits\" width=\"600\" height=\"460\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/01\/TypeTraits.PNG 744w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/01\/TypeTraits-300x230.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/h2>\n<h2>The Type-Traits Library<\/h2>\n<p>Type modification is the domain of <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-template-metaprogramming\">template metaprogramming <\/a>and, therefore, for the type-traits library.<\/p>\n<h3>Type Modifications<\/h3>\n<p>Maybe, you are curious about what is possible at compile time. A lot! Here are the most exciting metafunctions:<\/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;\">\/\/ const-volatile modifications:<\/span>\r\nremove_const;\r\nremove_volatile;\r\nremove_cv;\r\nadd_const;\r\nadd_volatile;\r\nadd_cv;\r\n   \r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ reference modifications:<\/span>\r\nremove_reference;\r\nadd_lvalue_reference;\r\nadd_rvalue_reference;\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ sign modifications:<\/span>\r\nmake_signed;\r\nmake_unsigned;\r\n \r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ pointer modifications:<\/span>\r\nremove_pointer;\r\nadd_pointer;\r\n \r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ other transformations:<\/span>\r\ndecay;\r\nenable_if;\r\nconditional;\r\ncommon_type;\r\nunderlying_type;\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>To get an <span style=\"font-family: courier new, courier;\">int<\/span> from <span style=\"font-family: courier new, courier;\">int<\/span> or <span style=\"font-family: courier new, courier;\">const int<\/span>, you must ask for the type with <span style=\"font-family: courier new, courier;\">::type<\/span>.<\/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: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>is_same<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, std<span style=\"color: #555555;\">::<\/span>remove_const<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;::<\/span>type<span style=\"color: #555555;\">&gt;::<\/span>value;        <span style=\"color: #0099ff; font-style: italic;\">\/\/ true<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>is_same<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, std<span style=\"color: #555555;\">::<\/span>remove_const<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;::<\/span>type<span style=\"color: #555555;\">&gt;::<\/span>value;  <span style=\"color: #0099ff; font-style: italic;\">\/\/ true<\/span>\r\n  \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Since C++14, you can use <span style=\"font-family: 'courier new', courier;\">_t<\/span>&nbsp;to get the type, such as for&nbsp;<span style=\"font-family: courier new, courier;\">std::remove_const_t:<\/span><\/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: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>is_same<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">remove_const_t<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;&gt;::<\/span>value;        <span style=\"color: #0099ff; font-style: italic;\">\/\/ true<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>is_same<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">remove_const_t<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;&gt;::<\/span>value;  <span style=\"color: #0099ff; font-style: italic;\">\/\/ true<\/span>\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>To get an idea of how valuable these metafunctions from the type-traits library are, here are a few use cases. Here is <span style=\"font-family: courier new, courier;\">std::move<\/span> in one line.<\/p>\n<ul>\n<li><span style=\"font-family: courier new, courier;\"><strong>remove_reference<\/strong>:<\/span> <span style=\"font-family: courier new, courier;\">std::move<\/span> and <span style=\"font-family: courier new, courier;\">std::forward<\/span> uses this function to remove the reference from its argument. \n<ul>\n<li>\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">static_cast<\/span><span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>remove_reference<span style=\"color: #555555;\">&lt;<\/span>decltype(arg)<span style=\"color: #555555;\">&gt;::<\/span>type<span style=\"color: #555555;\">&amp;&amp;&gt;<\/span>(arg);<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong><span style=\"font-family: courier new, courier;\">decay<\/span>:<\/strong> <span style=\"font-family: courier new, courier;\">std::thread <\/span>applies<span style=\"font-family: courier new, courier;\"> std::decay<\/span> to its arguments. Their usage includes the function<span style=\"font-family: courier new, courier;\"> f<\/span> a thread executes on its arguments <span style=\"font-family: courier new, courier;\">args<\/span>. Decay means that implicit conversions from array-to-pointer, and function-to-pointer is performed, and const\/volatile qualifiers and references are removed.<code><\/code><span style=\"font-family: courier new, courier;\"> <\/span>\n<ul>\n<li>\n<div class=\"mw-geshi\" dir=\"ltr\" style=\"text-align: left;\">\n<div class=\"cpp source-cpp\">\n<pre class=\"de1\"><a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/functional\/invoke\"><span class=\"kw1057\">std::<span class=\"me2\">invoke<\/span><\/span><\/a><span class=\"br0\">(<\/span>decay_copy<span class=\"br0\">(<\/span><a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/forward\"><span class=\"kw1114\">std::<span class=\"me2\">forward<\/span><\/span><\/a><span class=\"sy1\">&lt;<\/span>Function<span class=\"sy1\">&gt;<\/span><span class=\"br0\">(<\/span>f<span class=\"br0\">)<\/span><span class=\"br0\">)<\/span>, \r\n            decay_copy<span class=\"br0\">(<\/span><a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/forward\"><span class=\"kw1114\">std::<span class=\"me2\">forward<\/span><\/span><\/a><span class=\"sy1\">&lt;<\/span>Args<span class=\"sy1\">&gt;<\/span><span class=\"br0\">(<\/span>args<span class=\"br0\">)<\/span><span class=\"br0\">)<\/span>...<span class=\"br0\">)<\/span><span class=\"sy4\">;<\/span><\/pre>\n<\/div>\n<\/div>\n<\/li>\n<\/ul>\n<\/li>\n<li><span style=\"font-family: courier new, courier;\"><strong>enable_if<\/strong>: std::enable_if <\/span>is a convenient way to use SFINAE. SFINAE stands for <strong>S<\/strong>ubstitution<strong> F<\/strong>ailure <strong>I<\/strong>s <strong>N<\/strong>ot <strong>A<\/strong>n <strong>E<\/strong>rror and applies during overload resolution of a function template. When substituting the template parameter fails, the specialization is discarded from the overload set but causes no compiler error. <span style=\"font-family: courier new, courier;\">std::enable_if<\/span> is heavily used in <span style=\"font-family: courier new, courier;\">std::tuple<\/span>.<\/li>\n<li><span style=\"font-family: courier new, courier;\"><strong>conditional<\/strong>: std::conditional <\/span>is the ternary operator at compile time.<span style=\"font-family: courier new, courier;\"><br \/><\/span><\/li>\n<li><strong><span style=\"font-family: courier new, courier;\">common_type: <\/span><\/strong><span style=\"font-family: courier new, courier;\">std::common_type <\/span>determines the common type of a group of types.<\/li>\n<li><strong><span style=\"font-family: courier new, courier;\">underlying_type: <\/span><\/strong><span style=\"font-family: courier new, courier;\">std::underlying_type <\/span>determines the type of an<span style=\"font-family: courier new, courier;\"> enum.<\/span><\/li>\n<\/ul>\n<p>Maybe, you are not convinced about the benefit of the type traits library. Let me end my story with the type-traits with their primary goals: correctness and optimization.<\/p>\n<\/p>\n<h3>Correctness<\/h3>\n<p>Correctness means, on one hand, that you can use the type-traits libraries to implement concepts such as <span style=\"font-family: courier new, courier;\">Integral, SignedIntegral<\/span>, and <span style=\"font-family: courier new, courier;\">UnsignedIntegral.<\/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;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\nconcept <span style=\"color: #007788; font-weight: bold;\">bool<\/span> Integral() {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> is_integral<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value;\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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\nconcept <span style=\"color: #007788; font-weight: bold;\">bool<\/span> SignedIntegral() {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> Integral<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>() <span style=\"color: #555555;\">&amp;&amp;<\/span> is_signed<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value;\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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\nconcept <span style=\"color: #007788; font-weight: bold;\">bool<\/span> UnsignedIntegral() {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> Integral<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>() <span style=\"color: #555555;\">&amp;&amp;<\/span> <span style=\"color: #555555;\">!<\/span>SignedIntegral<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span>();\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>But it also means you can use them to make your algorithm safer. I used in my previous post, <a href=\"https:\/\/www.modernescpp.com\/index.php\/more-and-more-save\">More and More Safe, <\/a>the functions <span style=\"font-family: courier new, courier;\">std::is_integral, std::conditional, std::common_type,<\/span> and <span style=\"font-family: courier new, courier;\">std::enable_if<\/span> from the type-traits library to make the generic <span style=\"font-family: courier new, courier;\">gcd<\/span> algorithm successively safer.<\/p>\n<p>To get a better idea of the post <a href=\"https:\/\/www.modernescpp.com\/index.php\/more-and-more-save\">More and More Safe <\/a>, here is the starting point of my generic <span style=\"font-family: courier new, courier;\">gcd<\/span> algorithm.<\/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;\">\"gcd(100, 10)= \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/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  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"gcd(100, 33)= \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> gcd(<span style=\"color: #ff6600;\">100<\/span>, <span style=\"color: #ff6600;\">33<\/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> <span style=\"color: #cc3300;\">\"gcd(100, 0)= \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> gcd(<span style=\"color: #ff6600;\">100<\/span>, <span style=\"color: #ff6600;\">0<\/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;         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\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;     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> gcd(<span style=\"color: #ff6600;\">100<\/span>, <span style=\"color: #ff6600;\">10L<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;        <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/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>The output of the program shows two issues.<\/p>\n<p><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=\"600\" height=\"415\" style=\"display: block; margin-left: auto; margin-right: auto;\" 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: 600px) 100vw, 600px\" \/><\/p>\n<p>First, double (line 1) and the C-String (line 2) fail in the modulo operator. Second, using an integer and a long (line 3) should work. Both issues can be elegantly solved with the type-traits library.<\/p>\n<p>The type-traits are not only about correctness it&#8217;s also about optimization.<\/p>\n<h3>Optimization<\/h3>\n<p>The key idea of the type-traits library is relatively straightforward. The compiler analysis the used types and makes, based on this analysis decision about which code should run. In the case of the algorithm <span style=\"font-family: courier new, courier;\">std::copy, std::fill,<\/span> or <span style=\"font-family: courier new, courier;\">std::equal<\/span> of the standard template library, the algorithm is applied to each element of the range one-by-one or the entire memory. In the second case, C functions such as<span style=\"font-family: courier new, courier;\"> <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/string\/byte\/memcmp\">memcmp<\/a>, <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/string\/byte\/memset\">memset<\/a>, <\/span><a href=\"http:\/\/en.cppreference.com\/w\/cpp\/string\/byte\/memcpy\"><span style=\"font-family: courier new, courier;\">memcpy,<\/span> <\/a>or <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/string\/byte\/memmove\"><span style=\"font-family: courier new, courier;\">memmove<\/span><\/a> are used, making the algorithm faster. The slight difference between <span style=\"font-family: courier new, courier;\">memcpy<\/span> and <span style=\"font-family: courier new, courier;\">memmove<\/span> is that <span style=\"font-family: courier new, courier;\">memmove<\/span> can deal with overlapping memory areas. <span style=\"font-family: courier new, courier;\"><br \/><\/span><\/p>\n<p>The following three code snippets from the GCC 6 implementation clarify one point: The type-traits library checks help generate more optimized 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: #0099ff; font-style: italic;\">\/\/ fill  <\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ Specialization: for char types we can use memset.                   <\/span>\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> _Tp<span style=\"color: #555555;\">&gt;<\/span>\r\n  <span style=\"color: #006699; font-weight: bold;\">inline<\/span> <span style=\"color: #006699; font-weight: bold;\">typename<\/span>\r\n  __gnu_cxx<span style=\"color: #555555;\">::<\/span>__enable_if<span style=\"color: #555555;\">&lt;<\/span>__is_byte<span style=\"color: #555555;\">&lt;<\/span>_Tp<span style=\"color: #555555;\">&gt;::<\/span>__value, <span style=\"color: #007788; font-weight: bold;\">void<\/span><span style=\"color: #555555;\">&gt;::<\/span>__type         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n  __fill_a(_Tp<span style=\"color: #555555;\">*<\/span> __first, _Tp<span style=\"color: #555555;\">*<\/span> __last, <span style=\"color: #006699; font-weight: bold;\">const<\/span> _Tp<span style=\"color: #555555;\">&amp;<\/span> __c)\r\n  {\r\n    <span style=\"color: #006699; font-weight: bold;\">const<\/span> _Tp __tmp <span style=\"color: #555555;\">=<\/span> __c;\r\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">size_t<\/span> __len <span style=\"color: #555555;\">=<\/span> __last <span style=\"color: #555555;\">-<\/span> __first)\r\n    __builtin_memset(__first, <span style=\"color: #006699; font-weight: bold;\">static_cast<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">unsigned<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">&gt;<\/span>(__tmp), __len);\r\n  }\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ copy<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">bool<\/span> _IsMove, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> _II, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> _OI<span style=\"color: #555555;\">&gt;<\/span>\r\n  <span style=\"color: #006699; font-weight: bold;\">inline<\/span> _OI\r\n  __copy_move_a(_II __first, _II __last, _OI __result)\r\n  {\r\n    <span style=\"color: #006699; font-weight: bold;\">typedef<\/span> <span style=\"color: #006699; font-weight: bold;\">typename<\/span> iterator_traits<span style=\"color: #555555;\">&lt;<\/span>_II<span style=\"color: #555555;\">&gt;::<\/span>value_type _ValueTypeI;\r\n    <span style=\"color: #006699; font-weight: bold;\">typedef<\/span> <span style=\"color: #006699; font-weight: bold;\">typename<\/span> iterator_traits<span style=\"color: #555555;\">&lt;<\/span>_OI<span style=\"color: #555555;\">&gt;::<\/span>value_type _ValueTypeO;\r\n    <span style=\"color: #006699; font-weight: bold;\">typedef<\/span> <span style=\"color: #006699; font-weight: bold;\">typename<\/span> iterator_traits<span style=\"color: #555555;\">&lt;<\/span>_II<span style=\"color: #555555;\">&gt;::<\/span>iterator_category _Category;\r\n    <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> __simple <span style=\"color: #555555;\">=<\/span> (__is_trivial(_ValueTypeI)                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n                           <span style=\"color: #555555;\">&amp;&amp;<\/span> __is_pointer<span style=\"color: #555555;\">&lt;<\/span>_II<span style=\"color: #555555;\">&gt;::<\/span>__value\r\n                           <span style=\"color: #555555;\">&amp;&amp;<\/span> __is_pointer<span style=\"color: #555555;\">&lt;<\/span>_OI<span style=\"color: #555555;\">&gt;::<\/span>__value\r\n                           <span style=\"color: #555555;\">&amp;&amp;<\/span> __are_same<span style=\"color: #555555;\">&lt;<\/span>_ValueTypeI, _ValueTypeO<span style=\"color: #555555;\">&gt;::<\/span>__value);\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> std<span style=\"color: #555555;\">::<\/span>__copy_move<span style=\"color: #555555;\">&lt;<\/span>_IsMove, __simple,\r\n  }\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ lexicographical_compare<\/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> _II1, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> _II2<span style=\"color: #555555;\">&gt;<\/span>\r\n  <span style=\"color: #006699; font-weight: bold;\">inline<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span>\r\n  __lexicographical_compare_aux(_II1 __first1, _II1 __last1,\r\n\t\t\t\t  _II2 __first2, _II2 __last2)\r\n  {\r\n    <span style=\"color: #006699; font-weight: bold;\">typedef<\/span> <span style=\"color: #006699; font-weight: bold;\">typename<\/span> iterator_traits<span style=\"color: #555555;\">&lt;<\/span>_II1<span style=\"color: #555555;\">&gt;::<\/span>value_type _ValueType1;\r\n    <span style=\"color: #006699; font-weight: bold;\">typedef<\/span> <span style=\"color: #006699; font-weight: bold;\">typename<\/span> iterator_traits<span style=\"color: #555555;\">&lt;<\/span>_II2<span style=\"color: #555555;\">&gt;::<\/span>value_type _ValueType2;\r\n    <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">bool<\/span> __simple <span style=\"color: #555555;\">=<\/span>                                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n      (__is_byte<span style=\"color: #555555;\">&lt;<\/span>_ValueType1<span style=\"color: #555555;\">&gt;::<\/span>__value <span style=\"color: #555555;\">&amp;&amp;<\/span> __is_byte<span style=\"color: #555555;\">&lt;<\/span>_ValueType2<span style=\"color: #555555;\">&gt;::<\/span>__value\r\n       <span style=\"color: #555555;\">&amp;&amp;<\/span> <span style=\"color: #555555;\">!<\/span>__gnu_cxx<span style=\"color: #555555;\">::<\/span>__numeric_traits<span style=\"color: #555555;\">&lt;<\/span>_ValueType1<span style=\"color: #555555;\">&gt;::<\/span>__is_signed\r\n       <span style=\"color: #555555;\">&amp;&amp;<\/span> <span style=\"color: #555555;\">!<\/span>__gnu_cxx<span style=\"color: #555555;\">::<\/span>__numeric_traits<span style=\"color: #555555;\">&lt;<\/span>_ValueType2<span style=\"color: #555555;\">&gt;::<\/span>__is_signed\r\n       <span style=\"color: #555555;\">&amp;&amp;<\/span> __is_pointer<span style=\"color: #555555;\">&lt;<\/span>_II1<span style=\"color: #555555;\">&gt;::<\/span>__value\r\n       <span style=\"color: #555555;\">&amp;&amp;<\/span> __is_pointer<span style=\"color: #555555;\">&lt;<\/span>_II2<span style=\"color: #555555;\">&gt;::<\/span>__value);\r\n\r\n  <span style=\"color: #006699; font-weight: bold;\">return<\/span> std<span style=\"color: #555555;\">::<\/span>__lexicographical_compare<span style=\"color: #555555;\">&lt;<\/span>__simple<span style=\"color: #555555;\">&gt;::<\/span>__lc(__first1, __last1,\r\n                                                        __first2, __last2);\r\n  }\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Lines 1, 2, and 3 show that the type-traits library is used to generate more optimized code. My post <a href=\"https:\/\/www.modernescpp.com\/index.php\/type-traits-performance-matters\">Type-Traits: Performance Matters, <\/a>gives you more insight and has performance numbers with GCC and MSVC.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>With <span style=\"font-family: courier new, courier;\">constexpr<\/span>, programming at compile time escapes its expert niche and becomes a mainstream technique. <span style=\"font-family: courier new, courier;\">constexpr<\/span> is programming at compile time with the typical C++-Syntax.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The type-traits library supports type checks, type comparisons, and type modifications at compile time. Right! Today, I write about type modifications at compile time.<\/p>\n","protected":false},"author":21,"featured_media":5613,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[435,419],"class_list":["post-5615","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-template-metaprogramming","tag-type-traits"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5615","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=5615"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5615\/revisions"}],"predecessor-version":[{"id":6797,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5615\/revisions\/6797"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5613"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}