{"id":5180,"date":"2017-02-12T20:25:46","date_gmt":"2017-02-12T20:25:46","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-is-still-lazy\/"},"modified":"2023-06-26T12:23:18","modified_gmt":"2023-06-26T12:23:18","slug":"c-is-still-lazy","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-is-still-lazy\/","title":{"rendered":"C++ is Lazy: CRTP"},"content":{"rendered":"<p>In my previous post, <a href=\"https:\/\/www.modernescpp.com\/index.php\/recursion-list-manipulation-and-lazy-evaluation\">Recursion, List Manipulation, and Lazy Evaluation<\/a>, I wrote about the characteristics of functional programming:&nbsp; The story about lazy evaluation in C++ is short. Sorry to say, but I have forgotten templates. The two advanced techniques, CRTP and expression templates, are based on lazy evaluation.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<h2>CRTP<\/h2>\n<p>But what does CRTP mean? 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 means a technique in C++ in which a class <span style=\"font-family: courier new,courier;\">Derived<\/span> derives from a class template <span style=\"font-family: courier new,courier;\">Base. <\/span>The key is that <span style=\"font-family: courier new,courier;\">Base<\/span> has <span style=\"font-family: courier new,courier;\">Derived<\/span> as a template argument.<span style=\"font-family: courier new,courier;\"><\/span><code><\/code><code><\/code><\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">T<\/span>&gt;\r\n<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">Base<\/span>{\r\n...\r\n};\r\n\r\n<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">Derived<\/span> : <span style=\"color: #0000ff;\">public<\/span> Base&lt;Derived&gt;{\r\n...\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>If that is not mind-blowing and how does lazy evaluation kick in? At first lazy evaluation.<\/p>\n<\/p>\n<h3>As lazy as possible<\/h3>\n<p>The key observation for understanding the CRTP idiom is that the instantiation of a method of a class template happens only when needed. Proof?<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ lazy.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">T<\/span>&gt; \r\n<span style=\"color: #0000ff;\">struct<\/span> Lazy{\r\n    <span style=\"color: #2b91af;\">void<\/span> func() { std::cout &lt;&lt; <span style=\"color: #a31515;\">\"func\"<\/span> &lt;&lt; std::endl;}\r\n    <span style=\"color: #2b91af;\">void<\/span> func2(); <span style=\"color: #008000;\">\/\/ not defined<\/span>\r\n};\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n  \r\n  std::cout &lt;&lt; std::endl;\r\n    \r\n  Lazy&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; lazy;\r\n  lazy.func();\r\n  \r\n  std::cout &lt;&lt; std::endl;\r\n    \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Although the method <span style=\"font-family: courier new,courier;\">func2<\/span> (line 8) of the class,&nbsp; <span style=\"font-family: courier new,courier;\">Lazy<\/span> is only declared but not defined; the compiler accepts the program. Because I don&#8217;t call <span style=\"font-family: courier new,courier;\">func2,<\/span> I need no definition.<span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5164\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/lazy.png\" alt=\"lazy\" style=\"margin: 15px;\" width=\"353\" height=\"210\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/lazy.png 353w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/lazy-300x178.png 300w\" sizes=\"auto, (max-width: 353px) 100vw, 353px\" \/><\/p>\n<p>That is precisely the property that the CRTP uses because the definition of a method of class templates is only needed if called. The method&#8217;s declaration is sufficient for the instantiation of the base class. Therefore, you can implement static polymorphism.<\/p>\n<h3>Static Polymorphism<\/h3>\n<p>Static polymorphism is quite similar to dynamic polymorphism. But contrary to dynamic polymorphism with virtual methods, the dispatch of the method calls will occur at compile time. Now, we are at the center of the CRTP idiom.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n47\r\n48\r\n49\r\n50<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ crtp.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">typename<\/span> Derived&gt;\r\n<span style=\"color: #0000ff;\">struct<\/span> Base{\r\n  <span style=\"color: #2b91af;\">void<\/span> interface(){\r\n    <span style=\"color: #0000ff;\">static_cast<\/span>&lt;Derived*&gt;(<span style=\"color: #0000ff;\">this<\/span>)-&gt;implementation();\r\n  }\r\n  <span style=\"color: #2b91af;\">void<\/span> implementation(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Implementation Base\"<\/span> &lt;&lt; std::endl;\r\n  }\r\n};\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Derived1: Base&lt;Derived1&gt;{\r\n  <span style=\"color: #2b91af;\">void<\/span> implementation(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Implementation Derived1\"<\/span> &lt;&lt; std::endl;\r\n  }\r\n};\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Derived2: Base&lt;Derived2&gt;{\r\n  <span style=\"color: #2b91af;\">void<\/span> implementation(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Implementation Derived2\"<\/span> &lt;&lt; std::endl;\r\n  }\r\n};\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Derived3: Base&lt;Derived3&gt;{};\r\n\r\n<span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\n<span style=\"color: #2b91af;\">void<\/span> execute(T&amp; base){\r\n    base.interface();\r\n}\r\n\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n  \r\n  std::cout &lt;&lt; std::endl;\r\n  \r\n  Derived1 d1;\r\n  execute(d1);\r\n    \r\n  Derived2 d2;\r\n  execute(d2);\r\n  \r\n  Derived3 d3;\r\n  execute(d3);\r\n  \r\n  std::cout &lt;&lt; std::endl;\r\n  \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I use static polymorphism in the function template execution (lines 29 &#8211; 32). I invoke on each argument <span style=\"font-family: courier new,courier;\">base<\/span> the method <span style=\"font-family: courier new,courier;\">base.interface.<\/span> The method <span style=\"font-family: courier new,courier;\">Base::interface<\/span> in lines 7 &#8211; 9 is the critical point of the CRTP idiom. The methods dispatch to the implementation of the derived class<em><\/em>: <span style=\"font-family: courier new,courier;\">static_cast&lt;Derived*&gt;(this)-&gt;implementation()<\/span>.&nbsp; That is possible because the method will be instantiated when called. At this point in time, the derived classes<span style=\"font-family: courier new,courier;\"> <span style=\"font-family: courier new,courier;\">Derived1,<\/span> <span style=\"font-family: courier new,courier;\">Derived2<\/span>, a<\/span>nd<span style=\"font-family: courier new,courier;\"> <span style=\"font-family: courier new,courier;\">Derived3<\/span> <\/span>are fully defined. Therefore, the method <span style=\"font-family: courier new,courier;\"><span style=\"font-family: courier new,courier;\">Base::interface<\/span> <\/span>can use the details of its derived classes. Fascinating is the method <span style=\"font-family: courier new,courier;\">Base::implementation<\/span> (lines 10 &#8211; 12). This method plays the role of a default implementation for the static polymorphism for the class&nbsp; <span style=\"font-family: courier new,courier;\">Derived3<\/span> (line 27).<\/p>\n<p>Here is the output of the program.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5178\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/crtp.png\" alt=\"crtp\" style=\"margin: 15px;\" width=\"324\" height=\"155\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/crtp.png 324w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/crtp-300x144.png 300w\" sizes=\"auto, (max-width: 324px) 100vw, 324px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Admittedly, the only purpose of the example was to present the mechanic behind the static polymorphism. A convincing example is still missing. Here we are.<\/p>\n<h2>Mixins with CRTP<\/h2>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Mixin\">Mixins<\/a> are a popular concept in mixing classes in new code. Therefore, it&#8217;s an often-used technique in Python to change the behavior of a class by using multiple inheritances. Contrary to C++, it is legal in Python to have more than one method definition in a class hierarchy. Python uses that method that is first in the <a href=\"https:\/\/docs.python.org\/3\/glossary.html#term-method-resolution-order\">Method Resolution Order <\/a>(MRO).<\/p>\n<p>You can implement mixins in C++ by using CRTP. A prominent example is the class <span style=\"font-family: courier new,courier;\">std::enable_shared_from_this.<\/span> Using this class, you can create objects that return a&nbsp; <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> to themselves. You have to derive your class <span style=\"font-family: courier new,courier;\">MySharedClass<\/span> <span style=\"font-family: courier new,courier;\">public<\/span> from <span style=\"font-family: courier new,courier;\">std::enable_shared_from_this<\/span>. Now, your class <span style=\"font-family: courier new,courier;\">MySharedClass<\/span> has a method <span style=\"font-family: courier new,courier;\">shared_from_this<\/span> for creating <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> to its objects. You can read the details about <span style=\"font-family: courier new,courier;\">std::enable_shared_from_this<\/span> in my post <a href=\"https:\/\/www.modernescpp.com\/index.php\/specialities-of-std-shared-ptr\">Specialities of std::shared_ptr.<\/a><\/p>\n<p>An additional typical use-case for mixins is a class that you want to extend with the capability that their instances support the comparison of equality and inequality.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n47\r\n48\r\n49\r\n50\r\n51\r\n52\r\n53\r\n54\r\n55\r\n56<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ crtpEquality.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;string&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">Derived<\/span>&gt;\r\n<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">Equality<\/span>{};\r\n\r\n<span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">Derived<\/span>&gt;\r\n<span style=\"color: #2b91af;\">bool<\/span> <span style=\"color: #0000ff;\">operator<\/span> == (Equality&lt;Derived&gt; <span style=\"color: #0000ff;\">const<\/span>&amp; op1, Equality&lt;Derived&gt; <span style=\"color: #0000ff;\">const<\/span> &amp; op2){\r\n  Derived <span style=\"color: #0000ff;\">const<\/span>&amp; d1 = <span style=\"color: #0000ff;\">static_cast<\/span>&lt;Derived <span style=\"color: #0000ff;\">const<\/span>&amp;&gt;(op1);     \r\n  Derived <span style=\"color: #0000ff;\">const<\/span>&amp; d2 = <span style=\"color: #0000ff;\">static_cast<\/span>&lt;Derived <span style=\"color: #0000ff;\">const<\/span>&amp;&gt;(op2); \r\n  <span style=\"color: #0000ff;\">return<\/span> !(d1 &lt; d2) &amp;&amp; !(d2 &lt; d1);\r\n}\r\n\r\n<span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">Derived<\/span>&gt;\r\n<span style=\"color: #2b91af;\">bool<\/span> <span style=\"color: #0000ff;\">operator<\/span> != (Equality&lt;Derived&gt; <span style=\"color: #0000ff;\">const<\/span>&amp; op1, Equality&lt;Derived&gt; <span style=\"color: #0000ff;\">const<\/span> &amp; op2){\r\n  Derived <span style=\"color: #0000ff;\">const<\/span>&amp; d1 = <span style=\"color: #0000ff;\">static_cast<\/span>&lt;Derived <span style=\"color: #0000ff;\">const<\/span>&amp;&gt;(op1);     \r\n  Derived <span style=\"color: #0000ff;\">const<\/span>&amp; d2 = <span style=\"color: #0000ff;\">static_cast<\/span>&lt;Derived <span style=\"color: #0000ff;\">const<\/span>&amp;&gt;(op2); \r\n  <span style=\"color: #0000ff;\">return<\/span> !(op1 == op2);\r\n}\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Apple:<span style=\"color: #0000ff;\">public<\/span> Equality&lt;Apple&gt;{\r\n  Apple(<span style=\"color: #2b91af;\">int<\/span> s): size{s}{};\r\n  <span style=\"color: #2b91af;\">int<\/span> size;\r\n};\r\n\r\n<span style=\"color: #2b91af;\">bool<\/span> <span style=\"color: #0000ff;\">operator<\/span> &lt; (Apple <span style=\"color: #0000ff;\">const<\/span>&amp; a1, Apple <span style=\"color: #0000ff;\">const<\/span>&amp; a2){\r\n  <span style=\"color: #0000ff;\">return<\/span> a1.size &lt; a2.size;\r\n}\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Man:<span style=\"color: #0000ff;\">public<\/span> Equality&lt;Man&gt;{\r\n  Man(std::string n): name{n}{}\r\n  std::string name;\r\n};\r\n\r\n<span style=\"color: #2b91af;\">bool<\/span> <span style=\"color: #0000ff;\">operator<\/span> &lt; (Man <span style=\"color: #0000ff;\">const<\/span>&amp; m1, Man <span style=\"color: #0000ff;\">const<\/span>&amp; m2){\r\n  <span style=\"color: #0000ff;\">return<\/span> m1.name &lt; m2.name;\r\n}\r\n\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n  \r\n  std::cout &lt;&lt; std::boolalpha &lt;&lt; std::endl;\r\n  \r\n  Apple apple1{5};\r\n  Apple apple2{10}; \r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"apple1 == apple2: \"<\/span> &lt;&lt; (apple1 == apple2) &lt;&lt; std::endl;\r\n    \r\n  Man man1{<span style=\"color: #a31515;\">\"grimm\"<\/span>};\r\n  Man man2{<span style=\"color: #a31515;\">\"jaud\"<\/span>};\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"man1 != man2: \"<\/span> &lt;&lt; (man1 != man2) &lt;&lt; std::endl;\r\n  \r\n  std::cout &lt;&lt; std::endl;\r\n    \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I have implemented for the classes <span style=\"font-family: courier new,courier;\">Apple<\/span> and <span style=\"font-family: courier new,courier;\">Man<\/span> the smaller operator (lines 28 and 37). For further reasoning, I will only use the class <span style=\"font-family: courier new,courier;\">Man<\/span> for simplicity.&nbsp; The class <span style=\"font-family: courier new,courier;\">Man<\/span> is publicly derived (lines 32 &#8211; 35) from <span style=\"font-family: courier new,courier;\">Equality&lt;Man&gt;<\/span>. I have implemented for classes of the kind <span style=\"font-family: courier new,courier;\">Equality&lt;Derived&gt;<\/span> the equality (lines 9 &#8211; 14) and the inequality operator (lines 16 &#8211; 21). The inequality operator uses the equality operator (line 20). The equality operator uses the fact that the smaller operator is implemented for <span style=\"font-family: courier new,courier;\">Derived<\/span> (line 13). The equality operator and inequality operator convert its operands: <span style=\"font-family: courier new,courier;\">Derived const&amp;: Derived const&amp; d1 = static_cast&lt;Derived const&amp;&gt;(op1).<\/span><\/p>\n<p>Now, I can compare <span style=\"font-family: courier new,courier;\">Apple<\/span> and <span style=\"font-family: courier new,courier;\">Man<\/span> for equality and inequality.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5179\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/crtpEquality.png\" alt=\"crtpEquality\" style=\"margin: 15px;\" width=\"384\" height=\"142\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/crtpEquality.png 384w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/crtpEquality-300x111.png 300w\" sizes=\"auto, (max-width: 384px) 100vw, 384px\" \/><\/p>\n<h2>&nbsp;What&#8217;s next?<\/h2>\n<p>&nbsp;<\/p>\n<p>In addition to CRTP, expression templates are also based on lazy evaluation. Expression templates are &#8220;structures representing a computation at compile time, which are evaluated only<strong> as needed<\/strong> to produce efficient code for the entire computation&#8221; (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Expression_templates\">https:\/\/en.wikipedia.org\/wiki\/Expression_templates<\/a>). As needed, that is the point of lazy evaluation; therefore, expression templates are the topic of my <a href=\"https:\/\/www.modernescpp.com\/index.php\/expression-templates\">next post<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous post, Recursion, List Manipulation, and Lazy Evaluation, I wrote about the characteristics of functional programming:&nbsp; The story about lazy evaluation in C++ is short. Sorry to say, but I have forgotten templates. The two advanced techniques, CRTP and expression templates, are based on lazy evaluation.<\/p>\n","protected":false},"author":21,"featured_media":5164,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[365],"tags":[426,412],"class_list":["post-5180","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-functional","tag-crtp","tag-python"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5180","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=5180"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5180\/revisions"}],"predecessor-version":[{"id":6888,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5180\/revisions\/6888"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5164"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}