{"id":6202,"date":"2021-08-13T06:25:10","date_gmt":"2021-08-13T06:25:10","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/more-arbout-variadic-templates\/"},"modified":"2024-07-22T10:39:30","modified_gmt":"2024-07-22T10:39:30","slug":"more-arbout-variadic-templates","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/more-arbout-variadic-templates\/","title":{"rendered":"More about Variadic Templates &#8230;"},"content":{"rendered":"<p>There is a lot of power in the strange-looking three dots that are heavily used in the Standard Template Library. Today, I visualize the expansion of the three dots and show a few use cases.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6191\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/templates.png\" alt=\"templates\" width=\"650\" height=\"409\" \/><\/p>\n<p>Let me start this post by analyzing the pack expansion in variadic templates.<\/p>\n<h2>Pack Expansion<\/h2>\n<p>Here is a short reminder.<\/p>\n<p>A variadic template is a template that can have an arbitrary number of template parameters.<\/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: #006699; font-weight: bold;\">typename<\/span> ... Args<span style=\"color: #555555;\">&gt;<\/span>\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> variadicTemplate(Args ... args) { \n    . . . . <span style=\"color: #0099ff; font-style: italic;\">\/\/ four dots<\/span>\n}\n<\/pre>\n<\/div>\n<p>The ellipsis (<code>...<\/code>) makes <code>Args<\/code> or <code>args<\/code> a so-called parameter pack. Precisely, <code>Args<\/code> is a template parameter pack and <code>args <\/code>a function parameter pack. Two operations are possible with parameter packs. They can be packed and unpacked. If the ellipse is to the left of <code>Args<\/code>, the parameter pack will be packed; if it is to the right of <code>Args<\/code>, it will be unpacked. Because of the function template argument deduction, the compiler can derive the template arguments.<\/p>\n<p>Before I write about the pack expansion, I have to make a short disclaimer. Usually, you don&#8217;t apply pack expansion directly. You use variadic templates doing it automatically, using fold expression, or<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/if\"><code> constexpr if<\/code><\/a> in C++17. I will write about fold expressions and<code> constexpr if<\/code> in future posts. Visualizing pack expansions helps a lot for a better understanding of variadic templates and fold expressions.<\/p>\n<p data-id=\"d31cd0ecb6b7a1f933552f524bd0ffb7\">The usage of parameter packs obeys a typical pattern for class templates.<\/p>\n<ul data-id=\"19e7d38ceb52f4648497935ee9386fcd\">\n<li>Operate on the first element of the parameter pack and recursively invoke the operation on the remaining elements. This step reduces the parameter pack successively by its first element.<\/li>\n<li>The recursion ends after a finite number of steps.<\/li>\n<li>The boundary condition is typically a fully specialized template.<\/li>\n<\/ul>\n<p>Thanks to this functional pattern for processing lists, you can calculate the product of numbers at compile time. In Lisp, you call the head of the list <code>ca<\/code>r, and the rest <code>cdr<\/code>. In Haskell, you call it <code>head<\/code> and <code>tail<\/code>.<\/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;\">\/\/ multVariadicTemplates.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> ...<span style=\"color: #555555;\">&gt;                                                <\/span><em> <span style=\"color: #0099ff;\">\/\/ (1)<\/span><\/em>\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Mult;\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;&gt;                                                        <\/span><span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Mult<span style=\"color: #555555;\">&lt;&gt;<\/span> {\n    <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> value <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>;\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> i, <span style=\"color: #007788; font-weight: bold;\">int<\/span> ... tail<span style=\"color: #555555;\">&gt;                                     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span><\/span>\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Mult<span style=\"color: #555555;\">&lt;<\/span>i, tail ...<span style=\"color: #555555;\">&gt;<\/span> {\n    <span style=\"color: #006699; font-weight: bold;\">static<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> value <span style=\"color: #555555;\">=<\/span> i <span style=\"color: #555555;\">*<\/span> Mult<span style=\"color: #555555;\">&lt;<\/span>tail ...<span style=\"color: #555555;\">&gt;::<\/span>value;\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;\">'\\n'<\/span>;\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Mult&lt;10&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> Mult<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> '\\n';  <em><span style=\"color: #0099ff;\">\/\/ (4)<\/span><\/em>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Mult&lt;10,10,10&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> Mult<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">10<\/span><span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> '\\n';\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Mult&lt;1,2,3,4,5&gt;::value: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> Mult<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/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><code><\/code><code><\/code>The class template <code>Mult<\/code> consists of a primary template and two specializations. Since the primary template (1) is not needed, a declaration is sufficient in this case: <code>template&lt;int ...&gt; struct Mult<\/code>. The specializations of the class template exist for no element (2) and at least one element (3). If<code> Mult&lt;10,10,10&gt;::value<\/code> is called, the last template is used by successively calling the first element with the rest of the parameter pack so that the value expands to the product 10*10*10. In the final recursion, the parameter pack contains no elements, and the boundary condition comes into action:<code> template&lt;&gt; struct Mult&lt;&gt;<\/code> (1). This returns the result of <code>Mult&lt;10,10,10&gt;::value= 10*10*10*1<\/code> at compile time.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6197\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/multVariadicTemplates.png\" alt=\"multVariadicTemplates\" width=\"400\" height=\"237\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/multVariadicTemplates.png 432w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/multVariadicTemplates-300x178.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>Now, to the exciting part: What happens under the hood? Let&#8217;s have a closer look at the call <code>Mult&lt;10,10,10&gt;::value<\/code>. This call triggers no recursion but a recursive instantiation. Here are the essential parts from<a href=\"https:\/\/cppinsights.io\/s\/af3c8d68\"> C++ Insights<\/a>:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6198\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/multInstantiation.png\" alt=\"multInstantiation\" width=\"400\" height=\"332\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/multInstantiation.png 474w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/multInstantiation-300x249.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/>The compiler generates full specializations for three (<code>Mult&lt;10, 10, 10&gt;<\/code>) and two arguments (<code>Mult&lt;10, 10&gt;<\/code>). You may ask yourself: Where are the instantiations for one (<code>Mult&lt;10&gt;<\/code>) and no argument (<code>Mult&lt;&gt;<\/code>).<code> Mult&lt;10&gt;<\/code> was already requested in (4) and <code>Mult&lt;&gt;<\/code> (1) is the boundary condition.<\/p>\n<p>Let me continue with an anecdote. When introducing <code><\/code>variadic templates, I ask my participants: Who of you ever used an ellipse? Half of my participants answer never. I answered them that I didn&#8217;t believe them and they may be heard from the <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/io\/c\/fprintf\">printf <\/a>family.<\/p>\n<h3>A Type-Safe <code>printf<\/code> Function<\/h3>\n<p>Of course, you know the C function printf: <span class=\"mw-geshi cpp source-cpp\"><code><span class=\"kw4\">int<\/span> printf<span class=\"br0\">(<\/span> <span class=\"kw4\">const<\/span> <span class=\"kw4\">char<\/span><span class=\"sy2\">*<\/span> format, ... <span class=\"br0\">)<\/span><\/code><span class=\"sy4\"><code>;. printf<\/code> is a function that can get an arbitrary number of arguments. Its power is based on the macro <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/variadic\/va_arg\">va_arg <\/a>and is not type-safe. Let&#8217;s implement a simplified <code>printf<\/code> function using variadic templates. This function is the<\/span><\/span> <code><\/code>hello world of variadic templates.<\/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;\">\/\/ myPrintf.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n \n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">myPrintf<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> format){                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> format;\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> ... Args<span style=\"color: #555555;\">&gt;<\/span>\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> myPrintf(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> format, T value, Args ... args){   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> ( ; <span style=\"color: #555555;\">*<\/span>format <span style=\"color: #555555;\">!=<\/span> <span style=\"color: #cc3300;\">'\\0'<\/span>; format<span style=\"color: #555555;\">++<\/span> ) {                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\n        <span style=\"color: #006699; font-weight: bold;\">if<\/span> ( <span style=\"color: #555555;\">*<\/span>format <span style=\"color: #555555;\">==<\/span> <span style=\"color: #cc3300;\">'%'<\/span> ) {                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (6) <\/span>\n           std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> value;\n           myPrintf(format <span style=\"color: #555555;\">+<\/span> <span style=\"color: #ff6600;\">1<\/span>, args ... );                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (7)<\/span>\n           <span style=\"color: #006699; font-weight: bold;\">return<\/span>;\n        }\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>format;                                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (8)<\/span>\n    }\n}\n \n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main(){\n    \n    myPrintf(<span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>);                                          <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n    \n    myPrintf(<span style=\"color: #cc3300;\">\"% world% %<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #cc3300;\">\"Hello\"<\/span>, <span style=\"color: #cc3300;\">'!'<\/span>, <span style=\"color: #ff6600;\">2011<\/span>);            <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n    \n    myPrintf(<span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>);                                          \n    \n}\n<\/pre>\n<\/div>\n<p>How does the code work? If <span style=\"font-family: courier new, courier;\">myPrintf<\/span> is invoked without a format string (1), (3) is used in the case. (2) uses the function template. The function templates loops (5) as long as the format symbol does not equal <span style=\"font-family: courier new, courier;\">`\\0`<\/span>. If the format symbol is not equal to <span style=\"font-family: courier new, courier;\">`\\0<\/span> , two control flows are possible. First, if the format starts with &#8216;<span style=\"font-family: 'courier new', courier;\">%<\/span>&#8216;\u00a0 (6), the first argument <span style=\"font-family: courier new, courier;\">value<\/span> is displayed<span style=\"font-family: courier new, courier;\">, <\/span>and <span style=\"font-family: courier new, courier;\">myPrintf<\/span> is once more invoked, but this time with a new format symbol and an argument less (7). Second, if the format string does not start with\u00a0<code>'<span style=\"font-family: courier new, courier;\">%<\/span><\/code>&#8216;, the format symbol is just displayed (line 8). The function <span style=\"font-family: courier new, courier;\">myPrintf<\/span> (3) is the boundary condition for the recursive calls.<\/p>\n<p>The output of the program is as expected.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5590\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/12\/myPrintf.png\" alt=\"myPrintf\" width=\"300\" height=\"187\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/12\/myPrintf.png 331w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/12\/myPrintf-300x187.png 300w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>As before,<a href=\"https:\/\/cppinsights.io\/s\/0b4200ca\"> C++ Insights<\/a> helps to gain more insight into the template instantiation process. Here are the three instantiations caused by<code> myPrintf(\"% world% %\\n\", \"Hello\", '!', 2011);:<\/code><\/p>\n<ul>\n<li>Four arguments:<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6199\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/fourArguments.png\" alt=\"fourArguments\" width=\"650\" height=\"246\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/fourArguments.png 795w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/fourArguments-300x114.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/fourArguments-768x291.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<ul>\n<li>Thee arguments:<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6200\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/threeArguments.png\" alt=\"threeArguments\" width=\"500\" height=\"268\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/threeArguments.png 562w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/threeArguments-300x161.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<ul>\n<li>Two arguments:<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6201\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/twoArguments.png\" alt=\"twoArguments\" width=\"450\" height=\"243\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/twoArguments.png 557w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/08\/twoArguments-300x162.png 300w\" sizes=\"auto, (max-width: 450px) 100vw, 450px\" \/><\/p>\n<h2>Short Two Weeks Break<\/h2>\n<p>Due to vacation and probably limited connectivity, I will not publish a post in the next two weeks. If you want to publish a guest post, please let me know.<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>In my <a href=\"https:\/\/www.modernescpp.com\/index.php\/the-first-big-update-of-my-c-20-book\">next post<\/a>, I will use variadic templates to implement the C++ idiom for a fully generic factory. One implementation of this life-saving C++ idiom is<code> std::make_unique<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There is a lot of power in the strange-looking three dots that are heavily used in the Standard Template Library. Today, I visualize the expansion of the three dots and show a few use cases.<\/p>\n","protected":false},"author":21,"featured_media":6191,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[376],"tags":[441],"class_list":["post-6202","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-templates","tag-variadic-templates"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6202","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=6202"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6202\/revisions"}],"predecessor-version":[{"id":9755,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6202\/revisions\/9755"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/6191"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}