{"id":5633,"date":"2019-02-15T09:08:20","date_gmt":"2019-02-15T09:08:20","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-big-surprises-with-specialisation-of-function-templates\/"},"modified":"2019-02-15T09:08:20","modified_gmt":"2019-02-15T09:08:20","slug":"c-core-guidelines-big-surprises-with-specialisation-of-function-templates","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-big-surprises-with-specialisation-of-function-templates\/","title":{"rendered":"C++ Core Guidelines: Surprise included with the Specialisation of Function Templates"},"content":{"rendered":"<p>Today, I finish the C++ core guidelines rules to templates with a big surprise for many C++ developers. I write about the specialization of function templates.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5630\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/animal-1821737_1280.jpg\" alt=\"animal 1821737 1280\" width=\"600\" height=\"400\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/animal-1821737_1280.jpg 1280w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/animal-1821737_1280-300x200.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/animal-1821737_1280-1024x683.jpg 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/animal-1821737_1280-768x512.jpg 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Let&#8217;s start simple. Here is a template specialization from a bird-eyes perspective.<\/p>\n<h2>Template Specialisation<\/h2>\n<p>Templates define the behavior of families of classes and functions. Often it is necessary that special types or non-types may be treated special. To support this use case, you fully specialize in templates. Class templates can even be partially specialized.<\/p>\n<p>Here is a code snippet to get a general idea.<\/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> T, <span style=\"color: #007788; font-weight: bold;\">int<\/span> Line, <span style=\"color: #007788; font-weight: bold;\">int<\/span> Column<span style=\"color: #555555;\">&gt;<\/span>     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Matrix<\/span>;\r\n\r\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;\">\/\/ (2)<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Matrix<\/span><span style=\"color: #555555;\">&lt;<\/span>T, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">3<\/span><span style=\"color: #555555;\">&gt;<\/span>{};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;&gt;<\/span>                                     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Matrix<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">3<\/span><span style=\"color: #555555;\">&gt;<\/span>{};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Line 1 is the primary or general template. This template must be declared at least and has to be declared before the partially or fully specialized templates. Line 2 follows with the partial specialization. Line 3 is the full specialization.&nbsp;<\/p>\n<p>To better understand partially and fully specialisation, I want to present a visual explanation. Think about an n-dimensional space of template parameters. In the primary template (line 1) you can choose an arbitrary type, and two arbitrary&nbsp;<span style=\"font-family: courier new, courier;\">int<\/span>&#8216;s. In the case of the partial specialization in line 2, you can only choose the type. This means the 3-dimensional space is reduced to a line. Fully specialization means that you have one point in a 3-dimensional space.&nbsp;<\/p>\n<p>What is happening when you invoke the templates?<\/p>\n<p>&nbsp;<\/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%;\">Matrix<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">3<\/span><span style=\"color: #555555;\">&gt;<\/span> m1;          <span style=\"color: #0099ff; font-style: italic;\">\/\/ class Matrix&lt;int, 3, 3&gt;<\/span>\r\n\r\nMatrix<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">double<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">3<\/span><span style=\"color: #555555;\">&gt;<\/span> m2;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ class Matrix&lt;T, 3, 3&gt; <\/span>\r\n\r\nMatrix<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>string, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">3<\/span><span style=\"color: #555555;\">&gt;<\/span> m3;  <span style=\"color: #0099ff; font-style: italic;\">\/\/ class Matrix&lt;T, Line, Column&gt; =&gt; ERROR<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new, courier;\">m1<\/span> uses the full specialization, <span style=\"font-family: courier new, courier;\">m2<\/span> uses the partial specialization, and <span style=\"font-family: courier new, courier;\">m3<\/span> the primary template which causes an error because the definition is missing.<\/p>\n<p>Here are three rules which the compiler uses to get the right specialization:<\/p>\n<ol>\n<li>The compiler finds only one specialisation. The compiler uses specialisation.<\/li>\n<li>The compiler finds more than one specialisation. The compiler uses the most specialized one. If this process ends in more than one specialization, the compiler throws an error.<\/li>\n<li>The compiler finds no specialisation. It uses the primary specialisation.<\/li>\n<\/ol>\n<p>Okay, I have to explain what A is a more specialized template than B means. Here is the informal definition of <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/partial_specialization\">cppreference.com<\/a>: &#8220;<em>A accepts a subset of the types that B accepts<\/em>&#8220;.<\/p>\n<p>After the first overview, I can dig a little bit deeper into function templates.<\/p>\n<\/p>\n<h2>Specialisation and Overloading of Function Templates<\/h2>\n<p>Function templates make the job of template specialization easier but also more difficult at the same time.<\/p>\n<ul>\n<li>Easier, because the function template only supports full specialisation.<\/li>\n<li>More difficult because function overloading comes into play.<\/li>\n<\/ul>\n<p>From the design perspective, you can specialize a function template with template specialization or overloading.<\/p>\n<p>&nbsp;<\/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;\">\/\/ functionTemplateSpecialisation.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n\r\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>\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName(T){\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"unknown type\"<\/span>;\r\n}\r\n\r\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>\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span>){\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"int\"<\/span>;\r\n}\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName(<span style=\"color: #007788; font-weight: bold;\">double<\/span>){  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"double\"<\/span>;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main(){\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"getTypeName(true): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> getTypeName(<span style=\"color: #336666;\">true<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"getTypeName(4711): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> getTypeName(<span style=\"color: #ff6600;\">4711<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"getTypeName(3.14): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> getTypeName(<span style=\"color: #ff6600;\">3.14<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Line 1 has the primary template, line 2 the full specialization for <span style=\"font-family: courier new, courier;\">int,<\/span> and line 3 the overload for <span style=\"font-family: courier new, courier;\">double. <\/span>Because I&#8217;m not interested in the values for the function or function templates, I skipped them: <span style=\"font-family: courier new, courier;\">std::string getTypeName(double)<\/span>, for example. The usage of the various functions is quite comfortable. The compiler deduces the types and the correct function or function template is invoked. In the case of the function overloading the compiler prefers the function overloading to the function template when the function overloading is a perfect fit.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5631\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/functionTemplateSpecialisation.png\" alt=\"functionTemplateSpecialisation\" width=\"400\" height=\"177\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/functionTemplateSpecialisation.png 528w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/functionTemplateSpecialisation-300x132.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/>But where is the big surprise I mentioned in the title of my post? Here it is.<span style=\"font-family: courier new, courier;\"> <\/span><\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-specialize-function\">T.144: Don\u2019t specialize function templates<\/a><\/h2>\n<p>The reason for the rules is quite short: function template specialization doesn&#8217;t participate in overloading. Let&#8217;s see what that means. My program is based on the program snippet from Demiov\/<a href=\"https:\/\/en.wikipedia.org\/wiki\/David_Abrahams_(computer_programmer)\">Abrahams<\/a>.<\/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;\">\/\/ dimovAbrahams.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ getTypeName<\/span>\r\n\r\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) primary template<\/span>\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName(T){\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"unknown\"<\/span>;\r\n}\r\n\r\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;\">\/\/ (2) primary template that overloads (1)<\/span>\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName(T<span style=\"color: #555555;\">*<\/span>){\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"pointer\"<\/span>;\r\n}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;&gt;<\/span>                      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3) explicit specialization of (2)<\/span>\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">*<\/span>){\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"int pointer\"<\/span>;\r\n}\r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ getTypeName2<\/span>\r\n\r\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;\">\/\/ (4) primary template<\/span>\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName2(T){\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"unknown\"<\/span>;\r\n}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;&gt;<\/span>                      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5) explicit specialization of (4)<\/span>\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName2(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">*<\/span>){\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"int pointer\"<\/span>;\r\n}\r\n\r\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;\">\/\/ (6) primary template that overloads (4)<\/span>\r\nstd<span style=\"color: #555555;\">::<\/span>string getTypeName2(T<span style=\"color: #555555;\">*<\/span>){\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"pointer\"<\/span>;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main(){\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #555555;\">*<\/span>p;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"getTypeName(p): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> getTypeName(p) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;   \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"getTypeName2(p): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> getTypeName2(p) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl; \r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Admittedly, the code looks quite dull but bear with me. I defined inline (1) the primary template&nbsp;<span style=\"font-family: courier new, courier;\">getTypeName.<\/span> Line 2 is an overload for pointers, and line 3 is a full specialization for an int pointer. In the case of <span style=\"font-family: courier new, courier;\">getTypeName2,<\/span> I made a small variation. I put the explicit specialization (line 5) before the overload for pointers (line 6).<\/p>\n<p>This reordering has surprising consequences.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5632\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/dimovAbrahams.png\" alt=\"dimovAbrahams\" width=\"300\" height=\"183\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/dimovAbrahams.png 356w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/02\/dimovAbrahams-300x183.png 300w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>In the first case, the full specialization for the <span style=\"font-family: courier new, courier;\">int<\/span> pointer is called, and in the second case, the overload of pointers. What?&nbsp; The reason for this non-intuitive behavior is that overload resolution ignores function template specialization. Overload resolution operates on primary templates and functions. In both cases, overload resolutions found both primary templates. In the first case (<span style=\"font-family: courier new, courier;\">getTypeName<\/span>), the pointer variant is the better fit, and, therefore, the explicit specialization for the <span style=\"font-family: courier new, courier;\">int<\/span> pointer was chosen. In the second variant (<span style=\"font-family: courier new, courier;\">getTypeName2<\/span>), the pointer variant was chosen, but the full specialization belongs to the primary template (line 4). Consequently, it was ignored.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>While proofreading these lines, I had an idea. Templates are good for more surprises. Therefore, I am making a short detour from the core guidelines, and I will present you with a few of them. My hope is that you will remember these lines if you encounter them.&nbsp;<\/p>\n<p>The future of C++ speaks templates. Therefore, it&#8217;s good to know more about their language.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, I finish the C++ core guidelines rules to templates with a big surprise for many C++ developers. I write about the specialization of function templates.<\/p>\n","protected":false},"author":21,"featured_media":5630,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[],"class_list":["post-5633","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5633","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=5633"}],"version-history":[{"count":0,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5633\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5630"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5633"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5633"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5633"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}