{"id":6213,"date":"2021-09-08T19:45:25","date_gmt":"2021-09-08T19:45:25","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/from-variadic-templates-to-fold-expressions\/"},"modified":"2024-07-22T10:44:25","modified_gmt":"2024-07-22T10:44:25","slug":"from-variadic-templates-to-fold-expressions","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/from-variadic-templates-to-fold-expressions\/","title":{"rendered":"From Variadic Templates to Fold Expressions"},"content":{"rendered":"<p>In my last two posts, &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/variadic-templates-or-the-power-of-three-dots\">Variadic Templates or the Power of Three Dots<\/a>&#8221; and &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/more-arbout-variadic-templates\">More about Variadic Templates<\/a>&#8220;, I introduced variadic templates. This post goes one step further in the future, and presents fold expressions that can directly reduce a parameter pack with a binary operator.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6208\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/templates.png\" alt=\"templates\" width=\"650\" height=\"399\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/templates.png 912w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/templates-300x184.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/templates-768x472.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>I intentionally skipped one import use case for variadic templates: the perfect factory function. When you combine perfect forwarding with variadic templates, you get the perfect factory function. The perfect factory function is a function that can accept an arbitrary number of arguments of any value category (lvalue or rvalue). Curious? Read my previous post, &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-variadic-templates\">C++ Core Guidelines: Rules for Variadic Templates<\/a>&#8220;.<\/p>\n<p>But now, I want to present something new with fold expressions.<\/p>\n<h2>Fold Expressions<\/h2>\n<p>C++11 supports variadic templates. These are templates that can accept an arbitrary number of template parameters. A so-called parameter pack holds an arbitrary number. Additionally, with C++17, we got fold expressions. You can directly reduce a parameter pack with a binary operator thanks to fold expressions. Let&#8217;s look at reducing an arbitrary number of numbers to a value.<\/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: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ variadicTemplatesFoldExpression.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold;\">bool<\/span> <span style=\"color: #cc00ff;\">allVar<\/span>() {                                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #336666;\">true<\/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: #006699; font-weight: bold;\">typename<\/span> ...Ts<span style=\"color: #555555;\">&gt;                         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span><\/span>\n<span style=\"color: #007788; font-weight: bold;\">bool<\/span> allVar(T t, Ts ... ts) {    <em>                            <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span><\/em>\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> t <span style=\"color: #555555;\">&amp;&amp;<\/span> allVar(ts...);                   <em><span style=\"color: #0099ff;\">            \/\/ (4)<\/span><\/em>\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>... Args<span style=\"color: #555555;\">&gt;                                 <span style=\"color: #555555;\">  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span><\/span><\/span>\n<span style=\"color: #007788; font-weight: bold;\">bool<\/span> all(Args... args) { <span style=\"color: #006699; font-weight: bold;\">return<\/span> (... <span style=\"color: #555555;\">&amp;&amp;<\/span> args); }            \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> std<span style=\"color: #555555;\">::<\/span>boolalpha;\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;\">\"allVar(): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> allVar() <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;\">\"all(): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> all() <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;\">\"allVar(true): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> allVar(<span style=\"color: #336666;\">true<\/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;\">\"all(true): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> all(<span style=\"color: #336666;\">true<\/span>) <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;\">\"allVar(true, true, true, false): \"<\/span> \n              <span style=\"color: #555555;\">&lt;&lt;<\/span> allVar(<span style=\"color: #336666;\">true<\/span>, <span style=\"color: #336666;\">true<\/span>, <span style=\"color: #336666;\">true<\/span>, <span style=\"color: #336666;\">false<\/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;\">\"all(true, true, true, false): \"<\/span> \n              <span style=\"color: #555555;\">&lt;&lt;<\/span> all(<span style=\"color: #336666;\">true<\/span>, <span style=\"color: #336666;\">true<\/span>, <span style=\"color: #336666;\">true<\/span>, <span style=\"color: #336666;\">false<\/span>) <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;\">'\\n'<\/span>;\n\n}\n<\/pre>\n<\/div>\n<p>Both function templates <span style=\"font-family: courier new,courier;\">allVar<\/span> and <span style=\"font-family: courier new,courier;\">all<\/span> return at compile time if all arguments are <span style=\"font-family: courier new,courier;\">true. allVar<\/span> uses variadic templates; <span style=\"font-family: courier new,courier;\">all<\/span> fold expressions.<\/p>\n<p>The variadic templates <code>allVar<\/code> applies recursion to evaluate its arguments. The function <span style=\"font-family: courier new,courier;\">allVar<\/span> (1) is the boundary condition if the parameter pack is empty. The recursion takes place in the function template <span style=\"font-family: courier new,courier;\">allVar<\/span> (2). The three dots stand for the so-called parameter pack. Parameter packs support two operations. You can pack or unpack them. It is packed in line (2); unpacked in (3) and (4).<\/p>\n<p>Line (4) requires our full attention. Here, the head of the parameter pack<span style=\"font-family: courier new,courier;\"> t<\/span> is combined with the rest<span style=\"font-family: courier new,courier;\"> ts<\/span> of the parameter pack ts using the binary operator &amp;&amp;. The call <span style=\"font-family: courier new,courier;\">allVar(ts &#8230;)<\/span> triggers the recursion. The call includes a parameter pack that is the original one reduced by the head. Fold expressions (5) make our job easier. With fold expressions, you can directly reduce the parameter pack with the help of the binary operator: <code>(... &amp;&amp; args)<\/code>.<\/p>\n<p>Here is the output of the program.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6209\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/variadicTemplatesFoldExpressios.png\" alt=\"variadicTemplatesFoldExpressios\" width=\"500\" height=\"275\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/variadicTemplatesFoldExpressios.png 579w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/variadicTemplatesFoldExpressios-300x165.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>A fold expression applies a binary operator to a parameter pack.<\/p>\n<h3>Application of the binary Operator<\/h3>\n<p>A fold expression can apply the binary operator in two different ways.<\/p>\n<ol>\n<li>With and without an initial value.<strong><br \/>\n<\/strong><\/li>\n<li>Fold the variadic pack from left or from right<strong><br \/>\n<\/strong><\/li>\n<\/ol>\n<p>There is a subtle difference between the algorithm <span style=\"font-family: courier new,courier;\">allVar<\/span> and <span style=\"font-family: courier new,courier;\">all.<\/span> <span style=\"font-family: courier new,courier;\">All<\/span> have the default value <code>true<\/code> for the empty parameter pack.<\/p>\n<p>C++17 supports 32 binary operators in fold expressions: &#8220;<span style=\"font-family: courier new,courier;\"><strong>+ &#8211; * \/ % ^ &amp; | = &lt; &gt; &lt;&lt; &gt;&gt; += -= *= \/= %= ^= &amp;= |= &lt;&lt;= &gt;&gt;= == != &lt;= &gt;= &amp;&amp; || , .* -&gt;*<\/strong><\/span>&#8221; . A few of them have default-values:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5162\" style=\"margin: 15px;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/BinaryOperatorDefault.png\" alt=\"BinaryOperatorDefault\" width=\"500\" height=\"129\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/BinaryOperatorDefault.png 674w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/BinaryOperatorDefault-300x77.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>You must provide an initial value for binary operators with no default value. You can specify an initial value for binary operators with a default value.<\/p>\n<p>If the ellipsis stands left of the parameter pack, the parameter pack will be processed from the left. If right of the parameter pack, it will be processed from the right. This is also true if you provide an initial value.<\/p>\n<p>Fold expression allows it to implement Haskell functions <span style=\"font-family: courier new,courier;\">foldl, foldr, foldl1,<\/span> and <span style=\"font-family: courier new,courier;\">foldr1 <\/span>directly in C++.<\/p>\n<h3>\u00a0A Flavor of Haskell<\/h3>\n<p>The following table shows the four variations of fold expression and their Haskell pendants. The C++17 standard requires that fold expressions with initial value use the same binary operator <span style=\"font-family: courier new,courier;\">op.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6210\" style=\"margin: 15px auto; display: block;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldExpressions2.png\" alt=\"foldExpressions\" width=\"550\" height=\"250\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldExpressions2.png 881w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldExpressions2-300x136.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldExpressions2-768x349.png 768w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/p>\n<p>The C++\u00a0 and Haskell variations differ in two points. The C++ version uses the default value as the initial value; the Haskell version uses the first element as the initial value. The C++ version processes the parameter pack at compile time, and the Haskell version processes its list at run time.<\/p>\n<p>The following program shows all four variations of fold expression. Each one subtracts a few numbers.<\/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;\">\/\/ foldVariations.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>... Args<span style=\"color: #555555;\">&gt;<\/span>                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> diffL1(Args <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span>... args) {\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> (... <span style=\"color: #555555;\">-<\/span> args);\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>... Args<span style=\"color: #555555;\">&gt;<\/span>                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> diffR1(Args <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span>... args) {\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> (args <span style=\"color: #555555;\">-<\/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> Init, <span style=\"color: #006699; font-weight: bold;\">typename<\/span>... Args<span style=\"color: #555555;\">&gt;<\/span>    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> diffL(Init init, Args <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span>... args) {\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> (init <span style=\"color: #555555;\">-<\/span> ... <span style=\"color: #555555;\">-<\/span> args);\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> Init, <span style=\"color: #006699; font-weight: bold;\">typename<\/span>... Args<span style=\"color: #555555;\">&gt;<\/span>    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> diffR(Init init, Args <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span>... args) {\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> (args <span style=\"color: #555555;\">-<\/span> ... <span style=\"color: #555555;\">-<\/span> init);\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;\">\"diffL1(1, 2, 3): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> diffL1(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1 - 2) - 3<\/span>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"diffR1(1, 2, 3): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> diffR1(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ 1 - (2 - 3)<\/span>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"diffL(10, 1, 2, 3): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> diffL(<span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>; <span style=\"color: #0099ff; font-style: italic;\">\/\/ ((10 - 1) - 2) - 3<\/span>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"diffR(10, 1, 2, 3): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> diffR(<span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>; <span style=\"color: #0099ff; font-style: italic;\">\/\/ 1 - (2 - (3 - 10))<\/span>\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 functions <code>diffL1<\/code> (1) and <code>diffL<\/code> (3) process the numbers from the left and the functions <code>diffR1<\/code> (2) and <code>diffR<\/code> (3) process them from the right. Additionally, the functions <code>diffL<\/code> and <code>diffR<\/code> use an initial start value. The comments in the <code>main<\/code> function shows the processing steps.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6211\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldVariations.png\" alt=\"foldVariations\" width=\"413\" height=\"268\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldVariations.png 413w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldVariations-300x195.png 300w\" sizes=\"auto, (max-width: 413px) 100vw, 413px\" \/><\/p>\n<p>I execute the Haskell pendant directly in the Haskell shell.<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6212\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldHaskell.png\" alt=\"foldHaskell\" width=\"385\" height=\"298\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldHaskell.png 385w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/09\/foldHaskell-300x232.png 300w\" sizes=\"auto, (max-width: 385px) 100vw, 385px\" \/><\/h2>\n<h2 style=\"margin: 0; line-height: 125%;\">What&#8217;s next?<\/h2>\n<p>Variadic templates, mainly fold expressions, enable concise expressions to be written for repeated operations. Learn more about it in my<a href=\"https:\/\/www.modernescpp.com\/index.php\/modern-c-collection\"> next post.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my last two posts, &#8220;Variadic Templates or the Power of Three Dots&#8221; and &#8220;More about Variadic Templates&#8220;, I introduced variadic templates. This post goes one step further in the future, and presents fold expressions that can directly reduce a parameter pack with a binary operator.<\/p>\n","protected":false},"author":21,"featured_media":6208,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[376],"tags":[442,441],"class_list":["post-6213","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-templates","tag-fold-expressions","tag-variadic-templates"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6213","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=6213"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6213\/revisions"}],"predecessor-version":[{"id":9757,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6213\/revisions\/9757"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/6208"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}