{"id":6245,"date":"2021-11-05T10:35:22","date_gmt":"2021-11-05T10:35:22","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/template-metaprogramming-how-it-works\/"},"modified":"2024-07-22T16:03:50","modified_gmt":"2024-07-22T16:03:50","slug":"template-metaprogramming-how-it-works","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/template-metaprogramming-how-it-works\/","title":{"rendered":"Template Metaprogramming &#8211; How it Works"},"content":{"rendered":"<p>In my last post, &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/template-metaprogramming-a-introduction\">Template Metaprogramming &#8211; How it All Started<\/a>&#8220;, I wrote about the roots of template metaprogramming. I presented the hello world of template metaprogramming: calculating the factorial of a number at compile time. In this post, I will write about how template metaprogramming can modify types at compile time.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6240\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/10\/TemplateMetaprogramming.png\" alt=\"TemplateMetaprogramming\" width=\"650\" height=\"403\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/10\/TemplateMetaprogramming.png 907w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/10\/TemplateMetaprogramming-300x186.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/10\/TemplateMetaprogramming-768x476.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/> The factorial program in the last post, &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/template-metaprogramming-a-introduction\">Template Metaprogramming &#8211; How it All Started<\/a>&#8221; was an excellent example but not idiomatic for template metaprogramming. Manipulating types at compile time is typical in template metaprogramming.<\/p>\n<h2>Type Manipulation at Compile Time<\/h2>\n<p>For example, here is what <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/move\">std::move<\/a> is conceptionally doing:<\/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: #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);\n<\/pre>\n<\/div>\n<p><code>std::move<\/code> takes its argument <code>arg<\/code>, deduces its type <code>(decltype(arg))<\/code>, removes its reference (<code>std::remove_reverence<\/code>), and casts it to an rvalue reference (<code>static_cast&lt;...&gt;::type&amp;&amp;&gt;<\/code>). Essentially,<br \/>\n<code>std::move<\/code> is an rvalue reference cast. Now, move semantics can kick in.<\/p>\n<p>How can a function remove constness from its argument?<\/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;\">\/\/ removeConst.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;type_traits&gt;<\/span>\n\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>\n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> removeConst {\n    <span style=\"color: #006699; font-weight: bold;\">using<\/span> type <span style=\"color: #555555;\">=<\/span> T;        <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n};\n\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>\n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> removeConst<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">&gt;<\/span> {\n    <span style=\"color: #006699; font-weight: bold;\">using<\/span> type <span style=\"color: #555555;\">=<\/span> T;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n};\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>boolalpha;\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_same<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, removeConst<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: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ true<\/span>    \n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>is_same<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, removeConst<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: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>; <span style=\"color: #0099ff; font-style: italic;\">\/\/ true<\/span>\n\n}\n<\/pre>\n<\/div>\n<p>I implemented <code>removeConst<\/code> the way <code>std::remove_const<\/code> is probably implemented in the <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\">type-traits library<\/a>. <code>std::is_same<\/code> from the type-traits library helps me to decide at compile-time if both types are the same. In case of<code> removeConst&lt;int&gt;<\/code> the primary or general class template kicks in; in case of<code> removeConst&lt;const int&gt;<\/code>, the partial specialization for <code>const T<\/code> applies. The critical observation is that both class templates return the underlying type in (1) and (2) via the alias <code>type<\/code>. As promised, the constness of the argument is removed.<\/p>\n<p>There are additional observations:<\/p>\n<ul>\n<li>Template specialization (partial or full) is conditional execution at compile-time. Let me be more specific: When I use <code>removeConst<\/code> a non-constant<code> int<\/code>, the compiler chooses the primary or general template. When I use a constant <code>int<\/code>, the compiler chooses the partial specialization for <code>const T<\/code>.<\/li>\n<li>The expression using <code>type = T<\/code> serves as the return value, which is, in this case, a type.<\/li>\n<li>When you study the program<a href=\"https:\/\/cppinsights.io\/s\/c9b121d0\"> removeConst.cpp<\/a> on C++ Insights, you see that the expression that the expression <code>std::is_same&lt;int, removeConst&lt;int&gt;::type&gt;::value<\/code> boils down to the boolean value <code>std::integral_constant&lt;bool, true&gt;::value<\/code> that is displayed as <code>true<\/code>.<\/li>\n<\/ul>\n<p>Let me step back and write about template metaprogramming for a more conceptual view.<\/p>\n<h2>More Meta<\/h2>\n<p>At run time, we use data and functions. At compile time, we use metadata and metafunctions. Quite logically, it&#8217;s called meta because we do metaprogramming.<\/p>\n<h3>Metadata<\/h3>\n<p><strong>Metadata are values that metafunctions us at compile time.<\/strong><\/p>\n<p>There are three types of values:<\/p>\n<ul>\n<li>Types such as int, or double<\/li>\n<li>Non-types such as integrals, enumerators, pointers, references, and floating-points with C++20<\/li>\n<li>Templates such as<code> std::vector<\/code>, or <code>std::deque<\/code><\/li>\n<\/ul>\n<p>You can read more about the three types of values in my previous post, &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/alias-templates-and-template-parameters\">Alias Templates and Template Parameters<\/a>&#8220;.<\/p>\n<h3>Metafunctions<\/h3>\n<p><strong>Metafunctions are functions that are executed at compile time.<\/strong><\/p>\n<p>Admittedly, this sounds strange: Types are used in template metaprogramming to simulate functions. Based on the definition of metafunctions, <code>constexpr<\/code> functions that can be executed at compile time, are also metafunctions. The same holds for <code>consteval<\/code> functions in C++20.<\/p>\n<p>Here are two metafunctions.<\/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: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span> a , <span style=\"color: #007788; font-weight: bold;\">int<\/span> b<span style=\"color: #555555;\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Product {\n    <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span> value <span style=\"color: #555555;\">=<\/span> a <span style=\"color: #555555;\">*<\/span> b;\n};\n\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>\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> removeConst<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">&gt;<\/span> {\n    <span style=\"color: #006699; font-weight: bold;\">using<\/span> type <span style=\"color: #555555;\">=<\/span> T;\n};\n<\/pre>\n<\/div>\n<p>The first metafunction <code>Product<\/code> returns a value, and the second one <code>removeConst<\/code> returns a type. The name value and type are just naming conventions for the return values. If a meta-function returns a value, it is called a value; if it returns a type, it is called a type. The <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\">type-traits library<\/a> follows exactly this naming convention.<\/p>\n<p>It is quite enlightening to compare functions with metafunctions.<\/p>\n<h3>Functions versus Metafunctions<\/h3>\n<p>The following function <code>power<\/code> and the metafunction <code>Power<\/code> calculate pow(2, 10) at run time and compile time.<\/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;\">\/\/ power.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">power<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> m, <span style=\"color: #007788; font-weight: bold;\">int<\/span> n) {                               \n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> r <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> k <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>; k <span style=\"color: #555555;\">&lt;=<\/span> n; <span style=\"color: #555555;\">++<\/span>k) r <span style=\"color: #555555;\">*=<\/span> m;\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> r;                                        \n}\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span> m, <span style=\"color: #007788; font-weight: bold;\">int<\/span> n<span style=\"color: #555555;\">&gt;<\/span>                              \n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Power {\n    <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span> value <span style=\"color: #555555;\">=<\/span> m <span style=\"color: #555555;\">*<\/span> Power<span style=\"color: #555555;\">&lt;<\/span>m, n<span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span><span style=\"color: #555555;\">&gt;::<\/span>value;\n};\n                          \n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span> m<span style=\"color: #555555;\">&gt;<\/span>                                     \n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Power<span style=\"color: #555555;\">&lt;<\/span>m, <span style=\"color: #ff6600;\">0<\/span><span style=\"color: #555555;\">&gt;<\/span> {                                   \n    <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span> value <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;                       \n};\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n\t\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\t\n\t\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"power(2, 10)= \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> power(<span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">10<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Power&lt;2,10&gt;::value= \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> Power<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">10<\/span><span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\t\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n}\n<\/pre>\n<\/div>\n<p>This is the main difference:<\/p>\n<ul>\n<li><strong>Arguments<\/strong>: The function arguments go into the round brackets (( &#8230; )), and the metafunction arguments go into the sharp brackets (<code>&lt; ...&gt;<\/code>). This observation also holds for defining the function and the meta function. The function uses round brackets and metafunction sharp brackets. Each metafunction argument produces a new type.<\/li>\n<li><strong>Return value<\/strong>: The function uses a return statement, and the meta function is a static integral constant value.<\/li>\n<\/ul>\n<p>I elaborate more on this comparison in the upcoming post <code>about constexpr<\/code> and <code>consteval<\/code> functions. Here is the output of the program.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5609\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/01\/power.png\" alt=\"power\" width=\"400\" height=\"214\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/01\/power.png 599w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/01\/power-300x160.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p><code>power<\/code> is executed at run time and <code>Power<\/code> at compile time, but what is happening in the following example?<\/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;\">\/\/ powerHybrid.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span> n<span style=\"color: #555555;\">&gt;<\/span>\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> Power(<span style=\"color: #007788; font-weight: bold;\">int<\/span> m){\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> m <span style=\"color: #555555;\">*<\/span> Power<span style=\"color: #555555;\">&lt;<\/span>n<span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span><span style=\"color: #555555;\">&gt;<\/span>(m);\n}\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;&gt;<\/span>\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> Power<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">0<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> m){\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">1<\/span>;\n}\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main() {\n    \n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Power&lt;0&gt;(10): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> Power<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">0<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">20<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Power&lt;1&gt;(10): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> Power<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">1<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">10<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Power&lt;2&gt;(10): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> Power<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">2<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">10<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n    \n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}\n<\/pre>\n<\/div>\n<p>The question is obvious: Is <code>Power<\/code> a function or a metafunction? I promise the answer to this question gives you more insight.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>In my next post, I will analyze the function\/metafunction <code>Power<\/code> and introduce the type-traits library. The type traits library is idiomatic for compile-time programming in C++.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my last post, &#8220;Template Metaprogramming &#8211; How it All Started&#8220;, I wrote about the roots of template metaprogramming. I presented the hello world of template metaprogramming: calculating the factorial of a number at compile time. In this post, I will write about how template metaprogramming can modify types at compile time.<\/p>\n","protected":false},"author":21,"featured_media":6240,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[376],"tags":[435],"class_list":["post-6245","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-templates","tag-template-metaprogramming"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6245","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=6245"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6245\/revisions"}],"predecessor-version":[{"id":9765,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6245\/revisions\/9765"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/6240"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}