{"id":5552,"date":"2018-11-08T18:54:48","date_gmt":"2018-11-08T18:54:48","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-template-interfaces\/"},"modified":"2023-06-26T10:30:14","modified_gmt":"2023-06-26T10:30:14","slug":"c-core-guidelines-template-interfaces","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-template-interfaces\/","title":{"rendered":"C++ Core Guidelines: Template Interfaces"},"content":{"rendered":"<p>This post is about template interfaces due to the C++ core guidelines: &#8220;&#8230;a critical concept&#8221;, because a template interface is &#8220;a contract between a user and an implementer &#8211; and should be carefully designed.&#8221;.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5550\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/automatic.jpg\" alt=\"automatic\" width=\"500\" height=\"282\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/automatic.jpg 1280w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/automatic-300x169.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/automatic-1024x576.jpg 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/automatic-768x432.jpg 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>Here are the rules for today:<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-essential\">T.41: Require only essential properties in a template\u2019s concepts<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-alias\">T.42: Use template aliases to simplify notation and hide implementation details<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-using\">T.43: Prefer <code class=\"highlighter-rouge no-highlight\">using<\/code> over <code class=\"highlighter-rouge no-highlight\">typedef<\/code> for defining aliases<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-deduce\">T.44: Use function templates to deduce class template argument types (where feasible)<\/a><\/li>\n<\/ul>\n<p>Let me start with the first rule T.41:<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-essential\">T.41: Require only essential properties in a template\u2019s concepts<\/a><\/h2>\n<p>What does it mean to specify only the essential properties? The guidelines provide an example of a sort algorithm that has debug support.<\/p>\n<div id=\"preview\">\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>Sortable S<span style=\"color: #555555;\">&gt;<\/span>\r\n    requires Streamable<span style=\"color: #555555;\">&lt;<\/span>S<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> sort(S<span style=\"color: #555555;\">&amp;<\/span> s)  <span style=\"color: #0099ff; font-style: italic;\">\/\/ sort sequence s<\/span>\r\n{\r\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (debug) cerr <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"enter sort( \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\")<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (debug) cerr <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"exit sort( \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\")<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<\/div>\n<p>One question remains: What is the issue if you specify non-essential properties? This means that your concepts are firmly bound to the implementation. The result may be that a slight change in the implementation changes your concepts. In the end, your interface becomes quite unstable.&nbsp;<\/p>\n<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-alias\">T.42: Use template aliases to simplify notation and hide implementation details<\/a><\/h2>\n<p>Since C++11, we have template aliases. A template alias is a name that refers to a family of types. Using them makes your code more readable and helps you to get rid of type traits. My previous post&nbsp; <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-definition-of-concepts-the-second\">C++ Core Guidelines: Definition of Concepts, the Second<\/a>, provides more information to type traits.<\/p>\n<p>Let&#8217;s see what the guidelines mean by readability. The first example uses type traits:<\/p>\n<div id=\"preview\">\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; 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: #555555;\">&gt;<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> user(T<span style=\"color: #555555;\">&amp;<\/span> c)\r\n{\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">typename<\/span> container_traits<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value_type x; <span style=\"color: #0099ff; font-style: italic;\">\/\/ bad, verbose<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n<\/pre>\n<\/div>\n<\/div>\n<p>Here is the corresponding case with template aliases.<\/p>\n<div id=\"preview\">\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; 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: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">using<\/span> Value_type <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">typename<\/span> container_traits<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;::<\/span>value_type;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">user2<\/span>(T<span style=\"color: #555555;\">&amp;<\/span> c)\r\n{\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    Value_type<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> x;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n<\/pre>\n<\/div>\n<\/div>\n<p>Readability is also the argument that holds for the next rule<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-using\">T.43: Prefer <code class=\"highlighter-rouge no-highlight\">using<\/code> over <code class=\"highlighter-rouge no-highlight\">typedef<\/code> for defining aliases<\/a><\/h2>\n<p>There are two arguments from the readability perspective to prefer <span style=\"font-family: Courier New, Courier, monospace;\">using <\/span>over <span style=\"font-family: Courier New, Courier, monospace;\">typedef<\/span>. First, <span style=\"font-family: Courier New, Courier, monospace;\">using <\/span>comes when used. Second, <span style=\"font-family: Courier New, Courier, monospace;\">using <\/span>it feels quite similar to <span style=\"font-family: Courier New, Courier, monospace;\">auto<\/span>. Additionally, <span style=\"font-family: 'courier new', courier;\">using<\/span> can easily be used for template aliases.<\/p>\n<div id=\"preview\">\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">typedef<\/span> <span style=\"color: #cc00ff;\">int<\/span> (<span style=\"color: #555555;\">*<\/span>PFI)(<span style=\"color: #007788; font-weight: bold;\">int<\/span>);     <span style=\"color: #0099ff; font-style: italic;\">\/\/ OK, but convoluted<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">using<\/span> PFI2 <span style=\"color: #555555;\">=<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> (<span style=\"color: #555555;\">*<\/span>)(<span style=\"color: #007788; font-weight: bold;\">int<\/span>);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ OK, preferred<\/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>\r\n<span style=\"color: #006699; font-weight: bold;\">typedef<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> (<span style=\"color: #555555;\">*<\/span>PFT)(T);       <span style=\"color: #0099ff; font-style: italic;\">\/\/ error (1) <\/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>\r\n<span style=\"color: #006699; font-weight: bold;\">using<\/span> PFT2 <span style=\"color: #555555;\">=<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span> (<span style=\"color: #555555;\">*<\/span>)(T);     <span style=\"color: #0099ff; font-style: italic;\">\/\/ OK<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p>The first two lines define a pointer to a function (<span style=\"font-family: Courier New, Courier, monospace;\">PFI <\/span>and <span style=\"font-family: Courier New, Courier, monospace;\">PFI2<\/span>) that takes an <span style=\"font-family: Courier New, Courier, monospace;\">int <\/span>and returns an <span style=\"font-family: Courier New, Courier, monospace;\">int<\/span>. In the first case, <span style=\"font-family: Courier New, Courier, monospace;\">typedef <\/span>is used, and in the second line <span style=\"font-family: Courier New, Courier, monospace;\">using<\/span>. The last two lines define a function template (<span style=\"font-family: Courier New, Courier, monospace;\">PFT2<\/span>) which takes a type parameter<span style=\"font-family: Courier New, Courier, monospace;\"> T<\/span> and returns an <span style=\"font-family: Courier New, Courier, monospace;\">int<\/span>.&nbsp; Line (1) is not valid.<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rt-deduce\">T.44: Use function templates to deduce class template argument types (where feasible)<\/a><\/h2>\n<p>The primary reason that we have too many <span style=\"font-family: courier new, courier;\">make_<\/span> functions, such as <span style=\"font-family: courier new, courier;\">std::make_tuple<\/span> or <span style=\"font-family: courier new, courier;\">std::make_unique<\/span> is that a function template can deduce its template arguments from its function arguments. During this process, the compiler applies a few simple conversions, such as removing the outermost <span style=\"font-family: courier new, courier;\">const\/volatile<\/span> qualifier and decaying C-arrays and functions to a pointer to the first element of the C-array or a pointer to the function.<\/p>\n<p>This automatic template argument deduction makes our life as a programmer much more straightforward.<\/p>\n<p>Instead of typing<\/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%;\">std<span style=\"color: #555555;\">::<\/span>tuple<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, <span style=\"color: #007788; font-weight: bold;\">double<\/span>, std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&gt;<\/span> myTuple <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #ff6600;\">2011<\/span>, <span style=\"color: #ff6600;\">20.11<\/span>, <span style=\"color: #cc3300;\">\"C++11\"<\/span>};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>you use the factory function <span style=\"font-family: courier new, courier;\">std::make_tuple<\/span>.<\/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;\">auto<\/span> myTuple <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_tuple(<span style=\"color: #ff6600;\">2011<\/span>, <span style=\"color: #ff6600;\">20.11<\/span>, <span style=\"color: #cc3300;\">\"C++11\"<\/span>);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Sadly, automatic template type deduction is in C++ only available for function templates. Why? Constructors of class templates are a particular static function. Right! With C++17, the compiler can deduce its template arguments from its constructor arguments. Here is the way to define <span style=\"font-family: courier new, courier;\">myTuple<\/span> in C++17.<\/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%;\">std<span style=\"color: #555555;\">::<\/span>tuple myTuple <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #ff6600;\">2017<\/span>, <span style=\"color: #ff6600;\">20.17<\/span>, <span style=\"color: #cc3300;\">\"C++17\"<\/span>};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>A noticeable effect of this C++17 feature is that most of the <span style=\"font-family: courier new, courier;\">make_<\/span> functions become obsolete with C++17.<\/p>\n<p>To know the details about class template argument deduction, including the argument deduction guide, read the post <a href=\"https:\/\/arne-mertz.de\/2017\/06\/class-template-argument-deduction\/\">Modern C++ Features &#8211; Class Template Argument Deduction<\/a> from Arne Mertz.<\/p>\n<h3>Teachability of C++<\/h3>\n<p>I have to admit; I like this C++17 feature. As a C++ trainer, my job is it to explain this difficult stuff. The more symmetric C++ becomes, the easier for me to speak about general ideas.&nbsp; Now I can say: &#8220;A template can automatically deduce its template arguments from its function arguments.&#8221;.&nbsp; In the past, I had to say this works only for function templates.<\/p>\n<p>Here is a simple example:<\/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;\">\/\/ templateArgumentDeduction.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&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>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> showMe(<span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">&amp;<\/span> t){\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> t <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\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>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> ShowMe{\r\n  ShowMe(<span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">&amp;<\/span> t){\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> t <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n  }\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\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  showMe(<span style=\"color: #ff6600;\">5.5<\/span>);          <span style=\"color: #0099ff; font-style: italic;\">\/\/ not showMe&lt;double&gt;(5.5);<\/span>\r\n  showMe(<span style=\"color: #ff6600;\">5<\/span>);            <span style=\"color: #0099ff; font-style: italic;\">\/\/ not showMe&lt;int&gt;(5);<\/span>\r\n    \r\n  ShowMe(<span style=\"color: #ff6600;\">5.5<\/span>);          <span style=\"color: #0099ff; font-style: italic;\">\/\/ not ShowMe&lt;double&gt;(5.5);<\/span>\r\n  ShowMe(<span style=\"color: #ff6600;\">5<\/span>);            <span style=\"color: #0099ff; font-style: italic;\">\/\/ not ShowMe&lt;int&gt;(5);<\/span>\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>The usage of the function template <span style=\"font-family: courier new, courier;\">showMe<\/span> or the class template <span style=\"font-family: courier new, courier;\">ShowMe<\/span> feels the same. From the user&#8217;s perspective, you don&#8217;t know you use a template.<\/p>\n<p>With a current GCC 8.2, the program compiles and runs.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5551\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/templateArgumentDeduction.png\" alt=\"templateArgumentDeduction\" width=\"700\" height=\"252\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/templateArgumentDeduction.png 1549w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/templateArgumentDeduction-300x108.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/templateArgumentDeduction-1024x368.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/templateArgumentDeduction-768x276.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/11\/templateArgumentDeduction-1536x552.png 1536w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>To be more specific, template argument deduction should work since GCC 7, Clang 5, and MSVC 19.14. <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/compiler_support\">cppreference.com <\/a>gives you the details of the compiler support.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Do you know what a Regular or SemiRegular type is? If not, the <a href=\"http:\/\/www.modernescpp.com\/index.php\/meeting-embedded-c-and-meeting-c\">next post<\/a> to template interfaces is just the right one for you. Rule T.46 states: &#8220;Require template arguments to be at least <span style=\"font-family: courier new, courier;\">Regular<\/span> or <span style=\"font-family: courier new, courier;\">SemiRegular.&#8221;.<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post is about template interfaces due to the C++ core guidelines: &#8220;&#8230;a critical concept&#8221;, because a template interface is &#8220;a contract between a user and an implementer &#8211; and should be carefully designed.&#8221;.<\/p>\n","protected":false},"author":21,"featured_media":5550,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[477],"class_list":["post-5552","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-interfaces"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5552","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=5552"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5552\/revisions"}],"predecessor-version":[{"id":6804,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5552\/revisions\/6804"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5550"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5552"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5552"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5552"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}