{"id":5138,"date":"2017-01-21T10:53:47","date_gmt":"2017-01-21T10:53:47","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/functional-in-c-17-and-c-20\/"},"modified":"2023-06-26T12:26:18","modified_gmt":"2023-06-26T12:26:18","slug":"functional-in-c-17-and-c-20","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/functional-in-c-17-and-c-20\/","title":{"rendered":"Functional in C++17 and C++20"},"content":{"rendered":"<p>Which functional feature can we expect with C++17, and for which functional feature can we hope with C++20? This is precisely the question I will concisely answer in this post.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p>With C++17 we get <span style=\"font-family: courier new,courier;\">fold expressions<\/span> and the new container <span style=\"font-family: courier new,courier;\">std::optional.<\/span> Even more thrilling becomes C++20. Concepts, the ranges library, and improved futures support new concepts in C++.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5135\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/timeline.FunktionalInCpp17Cpp20Eng.png\" alt=\"timeline.FunktionalInCpp17Cpp20Eng\" width=\"700\" height=\"334\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/timeline.FunktionalInCpp17Cpp20Eng.png 952w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/timeline.FunktionalInCpp17Cpp20Eng-300x143.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/timeline.FunktionalInCpp17Cpp20Eng-768x366.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>At first, to the near future. I will start in the next post with my systematic description of functional programming in C++. Therefore, I will be concise in this post. This post is only intended to make you more appetite.<\/p>\n<h2>C++17<\/h2>\n<h3>Fold expressions<\/h3>\n<p>C++11 has <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/parameter_pack\">Variadic Templates<\/a>. These are templates that can get an arbitrary number of arguments. The arbitrary number is bound in a parameter pack. New is with C++17 that you can directly reduce a parameter pack with a binary operator. Therefore, you can directly implement Haskell&#8217;s function family <span style=\"font-family: courier new,courier;\">foldl, foldr, foldl1,<\/span> and <span style=\"font-family: courier new,courier;\">foldr1, <\/span>which reduce a list to a value.<span style=\"font-family: courier new,courier;\"> <\/span><\/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<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ foldExpression.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>... Args&gt;\r\n<span style=\"color: #2b91af;\">bool<\/span> all(Args... args) { <span style=\"color: #0000ff;\">return<\/span> (... &amp;&amp; args); }\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span>... Args&gt;\r\n<span style=\"color: #2b91af;\">bool<\/span> any(Args... args) { <span style=\"color: #0000ff;\">return<\/span> (... || args); }\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span>... Args&gt;\r\n<span style=\"color: #2b91af;\">bool<\/span> none(Args... args) { <span style=\"color: #0000ff;\">return<\/span> not(... || args); }\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  std::cout &lt;&lt; std::boolalpha;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"all(true): \"<\/span> &lt;&lt; all(true) &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"any(true): \"<\/span> &lt;&lt; any(true) &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"none(true): \"<\/span> &lt;&lt; none(true) &lt;&lt; std::endl;\r\n  \r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"all(true, true, true, false): \"<\/span> &lt;&lt; all(true, true, true, false) &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"any(true, true, true, false): \"<\/span> &lt;&lt; any(true, true, true, false) &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"none(true, true, true, false): \"<\/span> &lt;&lt; none(true, true, true, false) &lt;&lt; std::endl;\r\n  \r\n  std::cout &lt;&lt; std::endl;\r\n  \r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"all(false, false, false, false): \"<\/span> &lt;&lt; all(false, false, false, false) &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"any(false, false, false, false): \"<\/span> &lt;&lt; any(false, false, false, false) &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"none(false, false, false, false): \"<\/span> &lt;&lt; none(false, false, false, false) &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>The function templates <span style=\"font-family: courier new,courier;\">all,<\/span> <span style=\"font-family: courier new,courier;\">any,<\/span> and <span style=\"font-family: courier new,courier;\">none<\/span> return at compile-time <span style=\"font-family: courier new,courier;\">true,<\/span> or <span style=\"font-family: courier new,courier;\">false<\/span>. I will have a closer look at the function template <span style=\"font-family: courier new,courier;\">any<\/span> in lines 5 and 6. The parameter pack (&#8230;) is unpacked on the binary operator (<span style=\"font-family: courier new,courier;\">&#8230; &amp;&amp; args<\/span>). The three dots define (ellipse) the parameter pack.<\/p>\n<p>For the program&#8217;s output, I use the online compiler on <a href=\"http:\/\/en.cppreference.com\/w\/\">cppreference.com<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5136\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/foldExpressions.png\" alt=\"foldExpressions\" style=\"margin: 15px;\" width=\"470\" height=\"299\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/foldExpressions.png 470w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/foldExpressions-300x191.png 300w\" sizes=\"auto, (max-width: 470px) 100vw, 470px\" \/><\/p>\n<p>Haskell has the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Monad_(functional_programming)#The_Maybe_monad\">maybe monad<\/a>, and C++17 will get <span style=\"font-family: courier new,courier;\">std::optional.<\/span><\/p>\n<\/p>\n<h3>std::optional<\/h3>\n<p><span style=\"font-family: courier new,courier;\">std::optional<\/span> stands for a calculation that maybe have a value. A find algorithm or a query of a hash table must deal with the fact that no value is available. Often, you use special values to indicate that you get no result. In short, a non-results. Often null pointers, empty strings, or special integer values are used for non-results. This is inconvenient and error-prone because you have to deal especially with non-result, and you have to distinguish the non-result from a regular result. In case of a non-result, you get with <span style=\"font-family: courier new,courier;\">std::optional<\/span> no value.&nbsp;<\/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<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ optional.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;experimental\/optional&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;vector&gt;<\/span>\r\n\r\nstd::experimental::optional&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; getFirst(<span style=\"color: #0000ff;\">const<\/span> std::vector&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;&amp; vec){\r\n  <span style=\"color: #0000ff;\">if<\/span> ( !vec.empty() ) <span style=\"color: #0000ff;\">return<\/span> std::experimental::optional&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;(vec[0]);\r\n  <span style=\"color: #0000ff;\">else<\/span> <span style=\"color: #0000ff;\">return<\/span> std::experimental::optional&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;();\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n    \r\n    std::vector&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; myVec{1,2,3};\r\n    std::vector&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; myEmptyVec;\r\n    \r\n    <span style=\"color: #0000ff;\">auto<\/span> myInt= getFirst(myVec);\r\n    \r\n    <span style=\"color: #0000ff;\">if<\/span> (myInt){\r\n        std::cout &lt;&lt; <span style=\"color: #a31515;\">\"*myInt: \"<\/span>  &lt;&lt; *myInt &lt;&lt; std::endl;\r\n        std::cout &lt;&lt; <span style=\"color: #a31515;\">\"myInt.value(): \"<\/span> &lt;&lt; myInt.value() &lt;&lt; std::endl;\r\n        std::cout &lt;&lt; <span style=\"color: #a31515;\">\"myInt.value_or(2017):\"<\/span> &lt;&lt; myInt.value_or(2017) &lt;&lt; std::endl;\r\n    }\r\n    \r\n    std::cout &lt;&lt; std::endl;\r\n    \r\n    <span style=\"color: #0000ff;\">auto<\/span> myEmptyInt= getFirst(myEmptyVec);\r\n    \r\n    <span style=\"color: #0000ff;\">if<\/span> (!myEmptyInt){\r\n        std::cout &lt;&lt; <span style=\"color: #a31515;\">\"myEmptyInt.value_or(2017):\"<\/span> &lt;&lt; myEmptyInt.value_or(2017) &lt;&lt; std::endl;\r\n    }\r\n   \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">std::optional<\/span> is currently in the namespace <span style=\"font-family: courier new,courier;\">experimental.<\/span> That will change with C++17. If it exists, the function getFirst will return the first element (line 8). If not, a <span style=\"font-family: courier new,courier;\">std::optional&lt;int&gt;<\/span> object. I use in the main function two vectors. The calls <span style=\"font-family: courier new,courier;\">getFirst<\/span> in lines 17 and 27 return a <span style=\"font-family: courier new,courier;\">std::optional<\/span> object. In the case of myInt (line 19), the object has a value; in the case of <span style=\"font-family: courier new,courier;\">myEmptyInt<\/span> (line 29), no value. Now, I can display the value of <span style=\"font-family: courier new,courier;\">myInt<\/span> (lines 20 &#8211; 22). The method <span style=\"font-family: courier new,courier;\">value_or<\/span> in lines 22 and 30 will return a value if <span style=\"font-family: courier new,courier;\">std::optional-object <\/span>has a value if not a default value.<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5137\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/optinal.png\" alt=\"optinal\" style=\"margin: 15px;\" width=\"470\" height=\"178\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/optinal.png 470w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/01\/optinal-300x114.png 300w\" sizes=\"auto, (max-width: 470px) 100vw, 470px\" \/><\/h2>\n<p>The impact of functional programming in C++ &#8211; particularly Haskell &#8211; increases significantly with C++20. Of course, it&#8217;s a little bit risky to predict C++20. I made a mistake once and said that the following features are part of C++17, which is, of course, not true.<\/p>\n<h2>C++20<\/h2>\n<p>Promised, the details of concepts, the ranges library, and the improved futures will follow in future posts.<\/p>\n<h3>Concepts<\/h3>\n<p><a href=\"https:\/\/de.wikipedia.org\/wiki\/Typklasse_(Informatik)\">Type classes<\/a> in Haskell are interfaces for similar types. If a type is a member of a type class, it will have specific properties. Type classes play in generic programming a similar role as interfaces in object-oriented programming. Inspired by type classes, you can specify requirements for the template parameters. The new functionality has the name <a href=\"https:\/\/isocpp.org\/blog\/2013\/02\/concepts-lite-constraining-templates-with-predicates-andrew-sutton-bjarne-s\">concepts<\/a>. For example, the sort algorithm requires that a template argument be sorted. <span style=\"font-family: courier new,courier;\"><\/span><\/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;\">typename<\/span> Cont&gt;\r\n  requires Sortable&lt;Cont&gt;()\r\n<span style=\"color: #2b91af;\">void<\/span> sort(Cont&amp; container){...}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>What are the benefits of concepts? At first, the template declaration states which properties must hold for the template arguments. Therefore, the compiler can detect the break of the contract and display an unambiguous error message.<\/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%;\">std::list&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; lst = {1998,2014,2003,2011};\r\nsort(lst); <span style=\"color: #008000;\">\/\/ ERROR: lst is no random-access container with &lt;<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The C++ community waits at least as eagerly for concepts as for the new <a href=\"https:\/\/github.com\/ericniebler\/range-v3\">ranges library<\/a> from Eric Niebler.<\/p>\n<h3>Ranges library<\/h3>\n<p>From the birds-eye perspective, the ranges library empowers you to apply the Standard Template Library algorithms directly on the whole container. But under the hood, we get new programming techniques.<\/p>\n<ul>\n<li>Lazy evaluation that enables you to apply the algorithm on infinite data streams.<\/li>\n<li>Thanks to the pipe symbol, we get function composition.<\/li>\n<li>Thanks to Range comprehension, you can directly create ranges similar to <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_comprehension\">list comprehension&nbsp;<\/a>in Python or Haskell.<\/li>\n<\/ul>\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\n2\r\n3\r\n4<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">  <span style=\"color: #0000ff;\">auto<\/span> odds= view::transform([](<span style=\"color: #2b91af;\">int<\/span> i){ <span style=\"color: #0000ff;\">return<\/span> i*i; }) |\r\n             view::remove_if([](<span style=\"color: #2b91af;\">int<\/span> i){ <span style=\"color: #0000ff;\">return<\/span> i % 2 == 0; }) |\r\n             view::take_while([](<span style=\"color: #2b91af;\">int<\/span> i){ <span style=\"color: #0000ff;\">return<\/span> i &lt; 1000; });\r\n  <span style=\"color: #0000ff;\">auto<\/span> oddNumbers= view::ints(1) | odds;\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">oddNumbers <\/span>holds, as a result, the square of all odd numbers smaller than 1000: 1, 9, 25, &#8230;, 841, 961. How does it work? The function composition calculates at first to each number is square (line 1), removes all even numbers (line 2), and stops if the square of numbers is greater than 1000 (line 3). I use <span style=\"font-family: courier new,courier;\">odds<\/span> in line number 4. <span style=\"font-family: courier new,courier;\">view::int(1)<\/span> creates the infinite input stream of integers starting with 0. Odds will stop the input stream<span style=\"font-family: courier new,courier;\">.<\/span><\/p>\n<p>There is proposal <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2013\/n3721.pdf\">n3721<\/a> for the improvement of futures. The main issue with C++11 futures is that you can not compose them. C++20 cleans it up.<\/p>\n<h3>Improved futures<\/h3>\n<p>The code snippet gives you an idea how the future of <span style=\"font-family: courier new,courier;\">std::future<\/span> will look like.<\/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<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; f1= async([]() {<span style=\"color: #0000ff;\">return<\/span> 123;});\r\nfuture&lt;string&gt; f2 = f1.then([](future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; f){ <span style=\"color: #0000ff;\">return<\/span> f.get().to_string(); });\r\n\r\nfuture&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; futures[] = {async([]() { <span style=\"color: #0000ff;\">return<\/span> intResult(125); }), \r\n                         async([]() { <span style=\"color: #0000ff;\">return<\/span> intResult(456); })};\r\nfuture&lt;vector&lt;future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;&gt;&gt; any_f = when_any(begin(futures), end(futures));\r\n\r\nfuture&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; futures[] = {async([]() { <span style=\"color: #0000ff;\">return<\/span> intResult(125); }), \r\n                         async([]() { <span style=\"color: #0000ff;\">return<\/span> intResult(456); })};\r\nfuture&lt;vector&lt;future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;&gt;&gt; all_f = when_all(begin(futures), end(futures));\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">f1.then<\/span> in line 2 returns a new future that will be executed if <span style=\"font-family: courier new,courier;\">f1<\/span> is done with its work. <span style=\"font-family: courier new,courier;\">any_f<\/span> (line 6) will be performed if one of the futures in lines 4 and 5 is done. <span style=\"font-family: courier new,courier;\">all_f<\/span> will be performed if all of the futures in lines 8 and 9 are done.<span style=\"font-family: courier new,courier;\"><\/span><span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<p>One question is still not answered in my post. What have futures with functional programming in common? A lot! The improved futures are a monad. Suppose you don&#8217;t believe me. Watch: <a href=\"https:\/\/bartoszmilewski.com\/2014\/02\/26\/c17-i-see-a-monad-in-your-future\/\">I see a Monad in your Future <\/a>(Bartosz Milewski).&nbsp;<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Now, it&#8217;s time to start with my systematic. In the <a href=\"https:\/\/www.modernescpp.com\/index.php\/the-definition-of-functional-programming\">next post<\/a>, I will answer the question: What is functional programming?<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><span id=\"transmark\"><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Which functional feature can we expect with C++17, and for which functional feature can we hope with C++20? This is precisely the question I will concisely answer in this post.<\/p>\n","protected":false},"author":21,"featured_media":5135,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[365],"tags":[508],"class_list":["post-5138","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-functional","tag-haskell"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5138","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=5138"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5138\/revisions"}],"predecessor-version":[{"id":6896,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5138\/revisions\/6896"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5135"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5138"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5138"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5138"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}