{"id":7769,"date":"2023-07-24T13:08:06","date_gmt":"2023-07-24T13:08:06","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=7769"},"modified":"2023-08-23T17:01:05","modified_gmt":"2023-08-23T17:01:05","slug":"c23-syntactic-sugar-with-deducing-this","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c23-syntactic-sugar-with-deducing-this\/","title":{"rendered":"C++23: Syntactic Sugar with Deducing This"},"content":{"rendered":"\n<p>The <strong>C<\/strong>uriously<strong> R<\/strong>ecurring <strong>T<\/strong>emplate <strong>P<\/strong>attern (CRTP) is a heavily used idiom in C++. It is similarly resistant to understanding as the classic design pattern visitor I presented in my last post: &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-23-deducing-this\">C++23: Deducing This<\/a>&#8220;.&nbsp; Thanks to deducing this, we can remove the C and R from the abbreviation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"579\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/DeducingThis-1-1030x579.png\" alt=\"\" class=\"wp-image-7770\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/DeducingThis-1-1030x579.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/DeducingThis-1-300x169.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/DeducingThis-1-768x432.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/DeducingThis-1-705x397.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/DeducingThis-1.png 1280w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h1-crtp\">CRTP<\/h2>\n\n\n\n<p>The acronym CRTP stands for the C++ idiom <strong>C<\/strong>uriously<strong> R<\/strong>ecurring <strong>T<\/strong>emplate <strong>P<\/strong>attern and denotes a technique in C++ in which a class <code>Derived<\/code> is derived from a class template <code>Base<\/code>. The critical point is that <code>Base<\/code> has <code>Derived<\/code> as a template argument.<\/p>\n\n\n\n<!-- HTML generated using hilite.me -->\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\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;\">typename<\/span> T<span style=\"color: #555555;\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Base<\/span>{\n    ...\n};\n\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Derived<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base<span style=\"color: #555555;\">&lt;<\/span>Derived<span style=\"color: #555555;\">&gt;<\/span>{\n    ...\n};\n<\/pre>\n<\/div>\n\n\n\n<p>CRTP is typically used to implement static polymorphism. Unlike dynamic polymorphism, static polymorphism happens at compile time and does not require an <em>expensive<\/em> run-time pointer indirection.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h1-1-c-98\">C++98<\/h3>\n\n\n\n<p>The following program<code> crtp.cpp<\/code> shows an idiomatic C++98-based implementation of CRTP.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ crtp.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: #006699; font-weight: bold\">typename<\/span> Derived<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Base{                                        \n  <span style=\"color: #007788; font-weight: bold\">void<\/span> interface(){                                 <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n    <span style=\"color: #006699; font-weight: bold\">static_cast<\/span><span style=\"color: #555555\">&lt;<\/span>Derived<span style=\"color: #555555\">*&gt;<\/span>(<span style=\"color: #006699; font-weight: bold\">this<\/span>)<span style=\"color: #555555\">-&gt;<\/span>implementation();\n  }\n  <span style=\"color: #007788; font-weight: bold\">void<\/span> implementation(){                            <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Implementation Base&quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Derived1<span style=\"color: #555555\">:<\/span> Base<span style=\"color: #555555\">&lt;<\/span>Derived1<span style=\"color: #555555\">&gt;<\/span>{\n  <span style=\"color: #007788; font-weight: bold\">void<\/span> implementation(){\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Implementation Derived1&quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Derived2<span style=\"color: #555555\">:<\/span> Base<span style=\"color: #555555\">&lt;<\/span>Derived2<span style=\"color: #555555\">&gt;<\/span>{\n  <span style=\"color: #007788; font-weight: bold\">void<\/span> implementation(){\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Implementation Derived2&quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Derived3<span style=\"color: #555555\">:<\/span> Base<span style=\"color: #555555\">&lt;<\/span>Derived3<span style=\"color: #555555\">&gt;<\/span>{};                <span style=\"color: #0099FF; font-style: italic\">\/\/ (4)<\/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>                             <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n<span style=\"color: #007788; font-weight: bold\">void<\/span> execute(T<span style=\"color: #555555\">&amp;<\/span> base){\n    base.interface();                              \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\">&#39;\\n&#39;<\/span>;\n  \n  Derived1 d1;\n  execute(d1);\n    \n  Derived2 d2;\n  execute(d2);\n  \n  Derived3 d3;\n  execute(d3);\n  \n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  \n}\n<\/pre><\/div>\n\n\n\n<p>The function template <code>execute<\/code> (1) uses static polymorphism. The member function<code> base::interface<\/code> (2) is the key to the CRTP idiom. The member function forwards to the implementation of the derived class:<code> static_cast&lt;derived*&gt;(this)-&gt;implementation<\/code>. This is possible because the function is not instantiated until it is called. The derived classes <code>Derived1<\/code>, <code>Derived2<\/code> and <code>Derived3<\/code> are defined at this point. Therefore, the function <code>Base::interface<\/code> can use the implementation of the derived classes. The member function <code>Base::implementation<\/code> (3) plays the role of a default implementation for the static polymorphism of the class <code>Derived3<\/code> (4).&nbsp;<\/p>\n\n\n\n<p>The following screenshot shows the static polymorphism in action.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"324\" height=\"155\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/crtp.png\" alt=\"\" class=\"wp-image-7771\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/crtp.png 324w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/crtp-300x144.png 300w\" sizes=\"auto, (max-width: 324px) 100vw, 324px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h1-2-c-23\">C++23<\/h3>\n\n\n\n<p>Thanks to the explicit object parameter (deducing this), the C and the R can be removed from the CRTP acronym:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"759\" height=\"121\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/CRTP_TP.png\" alt=\"\" class=\"wp-image-7772\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/CRTP_TP.png 759w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/CRTP_TP-300x48.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/CRTP_TP-705x112.png 705w\" sizes=\"auto, (max-width: 759px) 100vw, 759px\" \/><\/figure>\n\n\n\n<p>The program <code>deducingThisCRTP.cpp<\/code> shows the C++23-based implementation of <s>CR<\/s>TP.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ deducingThisCRTP.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Base{                                            <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\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> Self<span style=\"color: #555555\">&gt;<\/span>\n  <span style=\"color: #007788; font-weight: bold\">void<\/span> interface(<span style=\"color: #006699; font-weight: bold\">this<\/span> Self<span style=\"color: #555555\">&amp;&amp;<\/span> self){\n    self.implementation();\n  }\n  <span style=\"color: #007788; font-weight: bold\">void<\/span> implementation(){\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Implementation Base&quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Derived1<span style=\"color: #555555\">:<\/span> Base{\n  <span style=\"color: #007788; font-weight: bold\">void<\/span> implementation(){\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Implementation Derived1&quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Derived2<span style=\"color: #555555\">:<\/span> Base{\n  <span style=\"color: #007788; font-weight: bold\">void<\/span> implementation(){\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Implementation Derived2&quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n};\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Derived3<span style=\"color: #555555\">:<\/span> Base{};\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: #007788; font-weight: bold\">void<\/span> execute(T<span style=\"color: #555555\">&amp;<\/span> base){\n    base.interface();                                 <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/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\">&#39;\\n&#39;<\/span>;\n  \n  Derived1 d1;                                        <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n  execute(d1);\n    \n  Derived2 d2;                                        <span style=\"color: #0099FF; font-style: italic\">\/\/ (4)<\/span>\n  execute(d2);\n  \n  Derived3 d3;                                        <span style=\"color: #0099FF; font-style: italic\">\/\/ (5)<\/span>\n  execute(d3);\n  \n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  \n}\n<\/pre><\/div>\n\n\n\n<p>Thanks to the explicit object parameter (line 1), the type of the explicit object parameter can be deduced to the derived type and perfectly forwarded. For the concrete type in (2), <code>Derived1<\/code> (3), <code>Derived2<\/code> (4), and <code>Derived3<\/code> (5) are used. Consequently, the corresponding <em>virtual <\/em>function implementation is called: <code>std::forward&lt;Self&gt;(self).implementation()<\/code>. With the current Microsoft compiler, the program can already be executed:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"493\" height=\"248\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/deducingThisCRTP.png\" alt=\"\" class=\"wp-image-7777\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/deducingThisCRTP.png 493w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/07\/deducingThisCRTP-300x151.png 300w\" sizes=\"auto, (max-width: 493px) 100vw, 493px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h2-recursive-lambdas\">Recursive Lambdas<\/h2>\n\n\n\n<p>I got a comment on my last German post (<a href=\"https:\/\/www.heise.de\/forum\/heise-online\/Kommentare\/C-23-Deducing-This-erstellt-explizite-Zeiger\/rekursive-lambdas\/thread-7392252\/\">https:\/\/www.heise.de\/forum\/heise-online\/Kommentare\/C-23-Deducing-This-erstellt-explizite-Zeiger\/rekursive-lambdas\/thread-7392252\/<\/a>) that I forgot the most descriptive applications of Deducing This: recursive lambdas. Honestly, I&#8217;m not so sure because most programmers have issues with recursion. Second, I&#8217;m not a fan of sophisticated lambdas. Lambdas should be concise and self-documenting.<\/p>\n\n\n\n<p>Let me show you various implementations of a recursively defined factorial function. Afterward, you can decide which version you prefer.<\/p>\n\n\n\n<p>Each factorial function calculates the factorial of 10: 3628800.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h2-1-c-98\">C++98<\/h3>\n\n\n\n<p>In C++98, you have two options. Either you use template metaprogramming with recursive instantiation or just a function call. The template metaprogram runs at compile time.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ factorial_cpp98.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\">unsigned<\/span> <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> Factorial{\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> N <span style=\"color: #555555\">*<\/span> Factorial<span style=\"color: #555555\">&lt;<\/span>N<span style=\"color: #555555\">-<\/span><span style=\"color: #FF6600\">1<\/span><span style=\"color: #555555\">&gt;::<\/span>value;\n};\n\n\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;&gt;<\/span>                                                                     \n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Factorial<span style=\"color: #555555\">&lt;<\/span><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\">factorial<\/span>(<span style=\"color: #007788; font-weight: bold\">unsigned<\/span> <span style=\"color: #007788; font-weight: bold\">int<\/span> n){\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> n <span style=\"color: #555555\">&gt;<\/span> <span style=\"color: #FF6600\">0<\/span> <span style=\"color: #555555\">?<\/span> n <span style=\"color: #555555\">*<\/span> factorial(n <span style=\"color: #555555\">-<\/span> <span style=\"color: #FF6600\">1<\/span>)<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    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;Factorial&lt;10&gt;::value: &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> Factorial<span style=\"color: #555555\">&lt;<\/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\">&#39;\\n&#39;<\/span>; \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;factorial(10)         &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> factorial(<span style=\"color: #FF6600\">10<\/span>) <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    \n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n}\n<\/pre><\/div>\n\n\n\n<p>I&#8217;m not sure with which version of factorial you would prefer. I probably use the C++20 version based on <code>consteval<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h3-what-s-next\">What&#8217;s next?<\/h2>\n\n\n\n<p>The core language of C++23 has more features to offer than deducing this. They will be the topic of my next post.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Curiously Recurring Template Pattern (CRTP) is a heavily used idiom in C++. It is similarly resistant to understanding as the classic design pattern visitor I presented in my last post: &#8220;C++23: Deducing This&#8220;.&nbsp; Thanks to deducing this, we can remove the C and R from the abbreviation. CRTP The acronym CRTP stands for the [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":7770,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[378],"tags":[426],"class_list":["post-7769","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-23","tag-crtp"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7769","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=7769"}],"version-history":[{"count":20,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7769\/revisions"}],"predecessor-version":[{"id":8036,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7769\/revisions\/8036"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/7770"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=7769"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=7769"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=7769"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}