{"id":5940,"date":"2020-07-09T05:44:24","date_gmt":"2020-07-09T05:44:24","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-20-consteval-and-constinit\/"},"modified":"2023-06-26T09:47:46","modified_gmt":"2023-06-26T09:47:46","slug":"c-20-consteval-and-constinit","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-20-consteval-and-constinit\/","title":{"rendered":"Two new Keywords in C++20: consteval and constinit"},"content":{"rendered":"<p>With C++20, we get two new keywords: <span style=\"font-family: courier new, courier;\">consteval<\/span> and <span style=\"font-family: courier new, courier;\">constinit<\/span>. <span style=\"font-family: courier new, courier;\">consteval<\/span> produces a function executed at compile-time, and <span style=\"font-family: courier new, courier;\">constinit<\/span> guarantees that a variable is initialized at compile-time.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5199\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/TimelineCpp20.png\" alt=\"TimelineCpp20\" width=\"650\" height=\"234\" style=\"display: block; margin-left: auto; margin-right: auto;\" \/><\/p>\n<p>When you read my previous short description of <span style=\"font-family: courier new, courier;\">consteval<\/span> and <span style=\"font-family: courier new, courier;\">constinit<\/span> you may have the impression that both specifiers are pretty similar to <span style=\"font-family: courier new, courier;\">constexpr<\/span>. To make it short, you are right. Before I compare the keywords <span style=\"font-family: courier new, courier;\">consteval<\/span>, <span style=\"font-family: courier new, courier;\">constinit<\/span>, <span style=\"font-family: courier new, courier;\">constexpr<\/span>, and good old <span style=\"font-family: courier new, courier;\">const<\/span>, I have to introduce the new specifiers <span style=\"font-family: courier new, courier;\">consteval<\/span> and <span style=\"font-family: courier new, courier;\">constinit<\/span>.<\/p>\n<h2><span style=\"font-family: courier new, courier;\">consteval<\/span><\/h2>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">consteval <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">sqr<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n) {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">* <\/span>n;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new, courier;\">consteval<\/span> creates a so-called immediate function. Each invocation of an immediate function creates a compile-time constant. To say it more directly. A <span style=\"font-family: courier new, courier;\">consteval<\/span> (immediate) function is executed at compile-time.<\/p>\n<p><code>consteval<\/code> cannot be applied to destructors or functions which allocate or deallocate. You can only use at most one of <span style=\"font-family: courier new, courier;\">consteval<\/span>, <span style=\"font-family: courier new, courier;\">constexpr<\/span>, or <span style=\"font-family: courier new, courier;\">constinit<\/span> specifiers in a declaration. An immediate function (<span style=\"font-family: courier new, courier;\">consteval<\/span>) is implicit <span style=\"font-family: courier new, courier;\">inline<\/span> and must fulfill a constexpr function&#8217;s requirements.<\/p>\n<p>The requirements for a <span style=\"font-family: courier new, courier;\">constexpr<\/span> function in C++14 and, therefore, a <span style=\"font-family: courier new, courier;\">consteval<\/span> function is:<\/p>\n<p><span style=\"font-family: courier new, courier;\">A constexpr function<\/span> can<\/p>\n<ul>\n<li>have conditional jump instructions or loop instructions.<\/li>\n<li>have more than one instruction.<\/li>\n<li><span style=\"font-family: courier new, courier;\">invoke constexp<\/span> functions. A <span style=\"font-family: courier new, courier;\">consteval<\/span> function can only invoke a <span style=\"font-family: courier new, courier;\">constexpr<\/span> function but not the other way around.<\/li>\n<li>have fundamental data types that have to be initialized with a constant expression.<\/li>\n<\/ul>\n<p><span style=\"font-family: courier new, courier;\"><\/span><span style=\"font-family: courier new, courier;\">constexpr<\/span> functions can not have <span style=\"font-family: courier new, courier;\">static<\/span> or <span style=\"font-family: courier new, courier;\">thread_local<\/span> data. Neither can they have a<span style=\"font-family: courier new, courier;\"> try<\/span> block nor a <span style=\"font-family: courier new, courier;\">goto<\/span> instruction.<\/p>\n<p>The program <span style=\"font-family: courier new, courier;\">constevalSqr.cpp<\/span> applies the <span style=\"font-family: courier new, courier;\">consteval<\/span> function <span style=\"font-family: courier new, courier;\">sqr<\/span>.<\/p>\n<p><!-- HTML generated using hilite.me --><\/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;\">\/\/ constevalSqr.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\nconsteval <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">sqr<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n) {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">*<\/span> n;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"sqr(5): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> sqr(<span style=\"color: #ff6600;\">5<\/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    \r\n    <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> a <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">5<\/span>;                                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"sqr(a): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> sqr(a) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;     \r\n\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> b <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">5<\/span>;                                          <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ std::cout &lt;&lt; \"sqr(b): \" &lt;&lt; sqr(b) &lt;&lt; std::endl; ERROR<\/span>\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>5 is a constant expression and can be used as an argument for the function sqr (1).<\/p>\n<p>The same holds for variable <span style=\"font-family: courier new, courier;\">a <\/span>(2). A constant variable such as <span style=\"font-family: courier new, courier;\">a<\/span> is usable in a constant expression when it is initialized with a constant expression.<\/p>\n<p><span style=\"font-family: courier new, courier;\">b<\/span> (3) is not a constant expression. Consequently, the invocation of <span style=\"font-family: courier new, courier;\">sqr(b)<\/span> is not valid.<\/p>\n<p>Thanks to the brand-new GCC11 and the <a href=\"https:\/\/godbolt.org\/\">Compiler Explorer<\/a>, here is the program&#8217;s output.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5937\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/07\/constevalSqr.png\" alt=\"constevalSqr\" width=\"100\" height=\"45\" style=\"display: block; margin-left: auto; margin-right: auto;\" \/><\/p>\n<h2><span style=\"font-family: courier new, courier;\">constinit<\/span><\/h2>\n<p><span style=\"font-family: courier new, courier;\">constinit <\/span>can be applied to variables with static or thread storage duration. <span style=\"font-family: courier new, courier;\"> <\/span><\/p>\n<ul>\n<li><span style=\"font-family: courier new, courier;\">G<\/span>lobal (namespace) variables, static variables, or static class members have static storage duration. These objects are allocated when the program starts and deallocated when the program ends.<span style=\"color: #4d5156; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\"><br \/><\/span><\/li>\n<li><span style=\"font-family: courier new, courier;\">thread_local<\/span> variables have thread storage duration. Thread local data is created for each thread that uses this data.<span style=\"font-family: courier new, courier;\"> thread_local<\/span> data exclusively belongs to the thread. They are created at their first usage, and its lifetime is bound to the lifetime of the thread it belongs to. Often thread-local data is called thread-local storage.<\/li>\n<\/ul>\n<p><span style=\"font-family: courier new, courier;\">constinit<\/span> ensures that this kind of variable (static storage duration or thread storage duration) is initialized at compile-time.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/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;\">\/\/ constinitSqr.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\nconsteval <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">sqr<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n) {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">*<\/span> n;\r\n}\r\n\r\n    constexpr <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res1 <span style=\"color: #555555;\">=<\/span> sqr(<span style=\"color: #ff6600;\">5<\/span>);                  \r\n    constinit <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res2 <span style=\"color: #555555;\">=<\/span> sqr(<span style=\"color: #ff6600;\">5<\/span>);                 \r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"sqr(5): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> res1 <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;\">\"sqr(5): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> res2 <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n   \r\n    constinit thread_local <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res3 <span style=\"color: #555555;\">=<\/span> sqr(<span style=\"color: #ff6600;\">5<\/span>);     \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"sqr(5): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> res3 <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><span style=\"font-family: courier new, courier;\">res1<\/span> and <span style=\"font-family: courier new, courier;\">res2<\/span> have static storage duration. <span style=\"font-family: courier new, courier;\">res3<\/span>&nbsp; has thread storage duration.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5938\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/07\/constinitSqr.png\" alt=\"constinitSqr\" width=\"110\" height=\"65\" style=\"display: block; margin-left: auto; margin-right: auto;\" \/><\/p>\n<p>Now it&#8217;s time to write about the differences between <span style=\"font-family: courier new, courier;\">const<\/span>, <span style=\"font-family: courier new, courier;\">constexpr<\/span>, <span style=\"font-family: courier new, courier;\">consteval<\/span>, and <span style=\"font-family: courier new, courier;\">constinit<\/span>. Let me first write about function execution and then about variable initialization.<\/p>\n<\/p>\n<h2>Function Execution<\/h2>\n<p>&nbsp;The following program <span style=\"font-family: courier new, courier;\">consteval.cpp<\/span> has three versions of a<span style=\"font-family: courier new, courier;\"> <\/span>square function.<\/p>\n<p><!-- HTML generated using hilite.me --><\/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;\">\/\/ consteval.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;\">int<\/span> <span style=\"color: #cc00ff;\">sqrRunTime<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n) {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">*<\/span> n;\r\n}\r\n\r\nconsteval <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">sqrCompileTime<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n) {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">*<\/span> n;\r\n}\r\n\r\nconstexpr <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">sqrRunOrCompileTime<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n) {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">*<\/span> n;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ constexpr int prod1 = sqrRunTime(100); ERROR (1)<\/span>\r\n    constexpr <span style=\"color: #007788; font-weight: bold;\">int<\/span> prod2 <span style=\"color: #555555;\">=<\/span> sqrCompileTime(<span style=\"color: #ff6600;\">100<\/span>);\r\n    constexpr <span style=\"color: #007788; font-weight: bold;\">int<\/span> prod3 <span style=\"color: #555555;\">=<\/span> sqrRunOrCompileTime(<span style=\"color: #ff6600;\">100<\/span>);\r\n    \r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">100<\/span>;\r\n    \r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> prod4 <span style=\"color: #555555;\">=<\/span> sqrRunTime(x); \r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ int prod5 = sqrCompileTime(x); ERROR (2)<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> prod6 <span style=\"color: #555555;\">=<\/span> sqrRunOrCompileTime(x);\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>As the name suggests it. The ordinary function <span style=\"font-family: courier new, courier;\">sqrRunTime<\/span> runs at run-time; the <span style=\"font-family: courier new, courier;\">consteval<\/span> function <span style=\"font-family: courier new, courier;\">sqrCompileTime<\/span> runs at compile-time; the <span style=\"font-family: courier new, courier;\">constexpr<\/span> function <span style=\"font-family: courier new, courier;\">sqrRunOrCompileTime<\/span> can run at compile-time or run-time. Consequently, asking for the result at compile-time with <span style=\"font-family: courier new, courier;\">sqrRunTime<\/span> (1) is an error, or using a non-constant expression as an argument for <span style=\"font-family: courier new, courier;\">sqrCompileTime<\/span> (2) is an error.<\/p>\n<p>The difference between the <span style=\"font-family: courier new, courier;\">constexpr<\/span> function <span style=\"font-family: courier new, courier;\">sqrRunOrCompileTime<\/span> and the <span style=\"font-family: courier new, courier;\">consteval<\/span> function <span style=\"font-family: courier new, courier;\">sqrCompileTime<\/span> is that <span style=\"font-family: courier new, courier;\">sqrRunOrCompileTime<\/span> has only to run at compile-time when the context requires compile-time evaluation.<\/p>\n<p><!-- HTML generated using hilite.me --><!-- HTML generated using hilite.me --><\/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%;\">static_assert(sqrRunOrCompileTime(<span style=\"color: #ff6600;\">10<\/span>) <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">100<\/span>);                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ compile-time (1)<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> arrayNewWithConstExpressioFunction[sqrRunOrCompileTime(<span style=\"color: #ff6600;\">100<\/span>)]; <span style=\"color: #0099ff; font-style: italic;\">\/\/ compile-time (1)<\/span>\r\nconstexpr <span style=\"color: #007788; font-weight: bold;\">int<\/span> prod <span style=\"color: #555555;\">=<\/span> sqrRunOrCompileTime(<span style=\"color: #ff6600;\">100<\/span>);                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ compile-time (1)<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> a <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">100<\/span>;\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> runTime <span style=\"color: #555555;\">=<\/span> sqrRunOrCompileTime(a);                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ run-time (2)<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> runTimeOrCompiletime <span style=\"color: #555555;\">=<\/span> sqrRunOrCompileTime(<span style=\"color: #ff6600;\">100<\/span>);  <span style=\"color: #0099ff; font-style: italic;\">\/\/ run-time or compile-time (3)<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> allwaysCompileTime <span style=\"color: #555555;\">=<\/span> sqrCompileTime(<span style=\"color: #ff6600;\">100<\/span>);         <span style=\"color: #0099ff; font-style: italic;\">\/\/ compile-time (4)<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The first three lines (1) require compile-time evaluation. Line (2) can only be evaluated at run-time because <span style=\"font-family: courier new, courier;\">a<\/span> is not a constant expression. The critical line is (3). The function can be executed at compile-time or run-time. If it is executed at compile-time or run-time may depend on the compiler or the optimization level. This observation does not hold for line (4). A <span style=\"font-family: courier new, courier;\">consteval<\/span> function is always executed at compile-time.<\/p>\n<h2>Variable Initialization<\/h2>\n<p>&nbsp;In the following program <span style=\"font-family: courier new, courier;\">constexprConstinit.cpp<\/span>, I compare <span style=\"font-family: courier new, courier;\">const<\/span>, <span style=\"font-family: courier new, courier;\">constexpr<\/span>, and <span style=\"font-family: courier new, courier;\">constint<\/span>.<\/p>\n<p><!-- HTML generated using hilite.me --><\/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;\">\/\/ constexprConstinit.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\nconstexpr <span style=\"color: #007788; font-weight: bold;\">int<\/span> constexprVal <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1000<\/span>;\r\nconstinit <span style=\"color: #007788; font-weight: bold;\">int<\/span> constinitVal <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1000<\/span>;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">incrementMe<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> val){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">++<\/span>val;}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> val <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1000<\/span>;\r\n    <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res <span style=\"color: #555555;\">=<\/span> incrementMe(val);                                      <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> <span style=\"color: #cc3300;\">\"res: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> res <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    <br \/>    <span style=\"color: #0099ff; font-style: italic;\">\/\/ std::cout &lt;&lt; \"res: \" &lt;&lt; ++res &lt;&lt; std::endl;                       ERROR (2)<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ std::cout &lt;&lt; \"++constexprVal++: \" &lt;&lt; ++constexprVal &lt;&lt; std::endl; ERROR (2)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"++constinitVal++: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">++<\/span>constinitVal <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    constexpr <span style=\"color: #006699; font-weight: bold;\">auto<\/span> localConstexpr <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1000<\/span>;                                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ constinit auto localConstinit = 1000; ERROR<\/span>\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Only the <span style=\"font-family: courier new, courier;\">const<\/span> variable&nbsp; (1) is initialized at run-time. <span style=\"font-family: courier new, courier;\">constexpr<\/span> and <span style=\"font-family: courier new, courier;\">constinit<\/span> variables are initialized at compile-time.<\/p>\n<p><span style=\"font-family: courier new, courier;\">constinit<\/span> (3) does not imply constness such as <span style=\"font-family: courier new, courier;\">const<\/span> (2) or&nbsp; <span style=\"font-family: courier new, courier;\">constexpr<\/span>(2).&nbsp; A&nbsp; <span style=\"font-family: courier new, courier;\">constexpr<\/span> (4) or <span style=\"font-family: courier new, courier;\">const<\/span> (1) declared variable can be created as a local, but a <span style=\"font-family: courier new, courier;\">constinit<\/span> declared variable not.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5939\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/07\/constexprConstinit.png\" alt=\"constexprConstinit\" width=\"200\" height=\"44\" style=\"display: block; margin-left: auto; margin-right: auto;\" \/><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Initialization of static variables in different translation units has a severe issue: If the initialization of one static depends on another static, it is not defined in which sequence they are initialized. To make it short, my<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-static-initialization-order-fiasco\"> next post<\/a> is about the Static Initialization Order Fiasco and how you can solve it with <span style=\"font-family: 'courier new', courier;\">constinit<\/span>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>With C++20, we get two new keywords: consteval and constinit. consteval produces a function executed at compile-time, and constinit guarantees that a variable is initialized at compile-time.<\/p>\n","protected":false},"author":21,"featured_media":5199,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[429,461],"class_list":["post-5940","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-consteval","tag-constinit"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5940","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=5940"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5940\/revisions"}],"predecessor-version":[{"id":6734,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5940\/revisions\/6734"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5199"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5940"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5940"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5940"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}