{"id":5227,"date":"2017-03-24T21:05:59","date_gmt":"2017-03-24T21:05:59","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/cpp17-core\/"},"modified":"2017-03-24T21:05:59","modified_gmt":"2017-03-24T21:05:59","slug":"cpp17-core","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/cpp17-core\/","title":{"rendered":"C++17 &#8211; What&#8217;s New in the Core Language?"},"content":{"rendered":"<p>C++11, C++14, and C++17. I guess you see the pattern.&nbsp; Later this year, we will get a new C++ standard. In March 2017, the C++17 specification reached the Draft International Standard stage. Before I dive into the details, I will give you an overview of C++17.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p>Let me first look at the big picture.<\/p>\n<h2>The big picture<\/h2>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4724\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/04\/timeline.png\" alt=\"timeline\" width=\"700\" height=\"338\" style=\"margin: 15px;\" \/>&nbsp;<\/p>\n<p>Concerning C++98 to C++14, I only mentioned the big points. But, there is a C++ standard missing in my graphic: C++03. This is intentional because C++03 is a minimal C++ standard. More like a bug-fix release to C++98. If you know C++, you know, that the first ISO standard C++98 and the ISO standard C++11 are extensive standards. That will not hold for C++14 and in particular, for C++03.<\/p>\n<p>So the question is. Is C++17 a big C++ standard or a small one? From my perspective, the answer is relatively easy. C++17 is something in between C++14 and C++11. So, C++17 is neither big nor small. Why? Here comes my short answer.<\/p>\n<\/p>\n<h2>Overview<\/h2>\n<p>C++17 has a lot to offer. That will hold for the core language and the library. Let&#8217;s first look at the core language.<\/p>\n<h3>Core language<\/h3>\n<h4>Fold expressions<\/h4>\n<p>C++11 supports variadic templates. These are templates that can accept an arbitrary number of arguments. A parameter pack holds the arbitrary number. Additionally, with C++17, you can directly reduce a parameter pack with a binary operator:<\/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<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ foldExpressionAll.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: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::boolalpha;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"all(): \"<\/span> &lt;&lt; all() &lt;&lt; std::endl;\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;\">\"all(true, true, true, false): \"<\/span> &lt;&lt; all(true, true, true, 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>&nbsp;The binary operator is the logical AND in line 6. Here is the output of the program.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5225\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/foldExpression.png\" alt=\"foldExpression\" style=\"margin: 15px;\" width=\"438\" height=\"143\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/foldExpression.png 438w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/foldExpression-300x98.png 300w\" sizes=\"auto, (max-width: 438px) 100vw, 438px\" \/><\/p>\n<p>That&#8217;s all I have to say about fold expressions because I have already written a post about <a href=\"https:\/\/www.modernescpp.com\/index.php\/fold-expressions\">fold expressions<\/a>. So, there you have the details.<\/p>\n<p>We stay at compile time.<\/p>\n<h4>constexpr if<\/h4>\n<p><span style=\"font-family: courier new,courier;\">constexpr if<\/span> it enables it to compile source code conditionally.<\/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\n2\r\n3\r\n4\r\n5\r\n6\r\n7<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\n<span style=\"color: #0000ff;\">auto<\/span> get_value(T t) {\r\n    <span style=\"color: #0000ff;\">if<\/span> constexpr (std::is_pointer_v&lt;T&gt;)\r\n        <span style=\"color: #0000ff;\">return<\/span> *t; <span style=\"color: #008000;\">\/\/ deduces return type to int for T = int*<\/span>\r\n    <span style=\"color: #0000ff;\">else<\/span>\r\n        <span style=\"color: #0000ff;\">return<\/span> t;  <span style=\"color: #008000;\">\/\/ deduces return type to int for T = int<\/span>\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>If <span style=\"font-family: courier new,courier;\">T<\/span> is a pointer, the if branch in line 3 will be compiled. If not, the else branch is in line 5. Two points are essential to mention. The function <span style=\"font-family: courier new,courier;\">get_value<\/span> has two different return types, and both branches of the if the statement has to be valid.<\/p>\n<p>Consequently, what is possible with <span style=\"font-family: courier new,courier;\">for<\/span> statements is with C++17 possible with <span style=\"font-family: courier new,courier;\">if<\/span> and <span style=\"font-family: courier new,courier;\">switch<\/span> statements.<\/p>\n<h4>Initializers in if and switch statements<\/h4>\n<p>You can directly initialize your variable inside the <span style=\"font-family: courier new,courier;\">if<\/span> and <span style=\"font-family: courier new,courier;\">switch<\/span> statement.<\/p>\n<p>&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\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">std::map&lt;<span style=\"color: #2b91af;\">int<\/span>,std::string&gt; myMap;\r\n\r\n<span style=\"color: #0000ff;\">if<\/span> (<span style=\"color: #0000ff;\">auto<\/span> result = myMap.insert(value); result.second){\r\n    useResult(result.first);  \r\n    <span style=\"color: #008000;\">\/\/ ...<\/span>\r\n} \r\n<span style=\"color: #0000ff;\">else<\/span>{\r\n    <span style=\"color: #008000;\">\/\/ ...<\/span>\r\n} <span style=\"color: #008000;\">\/\/ result is automatically destroyed<\/span>\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Therefore, the variable <span style=\"font-family: courier new,courier;\">result<\/span> is valid inside the<span style=\"font-family: courier new,courier;\"> if<\/span> and <span style=\"font-family: courier new,courier;\">else<\/span> branches of the <span style=\"font-family: courier new,courier;\">if<\/span> statement. But <span style=\"font-family: courier new,courier;\">result<\/span> will not pollute the outer scope.<\/p>\n<p>If you use the initializer in <span style=\"font-family: courier new,courier;\">if<\/span> and <span style=\"font-family: courier new,courier;\">switch<\/span> statements in combination with the structured binding declaration, the C++ syntax will be more elegant.<\/p>\n<h4>Structured binding declarations<\/h4>\n<p>Thanks to the structured binding, you can bind a <span style=\"font-family: courier new,courier;\">std::tuple<\/span> or a <span style=\"font-family: courier new,courier;\">struct<\/span> directly to variables. Therefore I can still improve my last example.<\/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\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">std::map&lt;<span style=\"color: #2b91af;\">int<\/span>,std::string&gt; myMap;\r\n                \r\n<span style=\"color: #0000ff;\">if<\/span> (<span style=\"color: #0000ff;\">auto<\/span> [iter, succeeded] = myMap.insert(value); succeeded) {\r\n    useIter(iter);  \r\n    <span style=\"color: #008000;\">\/\/ ...<\/span>\r\n}\r\n<span style=\"color: #0000ff;\">else<\/span>{\r\n    <span style=\"color: #008000;\">\/\/ ...<\/span>\r\n} iter and succeded are automatically be destroyed\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;\">auto [iter, succeeded]<\/span> in line 3 automatically creates the two variables <span style=\"font-family: courier new,courier;\">iter<\/span> and <span style=\"font-family: courier new,courier;\">succeeded. <\/span>They will be destroyed at line 9.<span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<p>One of these features that make programming less cumbersome. The same holds for template deduction of constructors.<\/p>\n<h4>Template deduction of constructors<\/h4>\n<p>A function template can deduce its type parameters from its function arguments. But that was not possible for a unique function template: the constructor of a class template. With C++17, this statement is simply wrong. A constructor can deduce its type parameters from its constructor arguments.<\/p>\n<p>&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<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ templateArgumentDeduction.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> T&gt;\r\n<span style=\"color: #2b91af;\">void<\/span> showMe(<span style=\"color: #0000ff;\">const<\/span> T&amp; t){\r\n  std::cout &lt;&lt; t &lt;&lt; std::endl;\r\n}\r\n\r\n<span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\n<span style=\"color: #0000ff;\">struct<\/span> ShowMe{\r\n  ShowMe(<span style=\"color: #0000ff;\">const<\/span> T&amp; t){\r\n    std::cout &lt;&lt; t &lt;&lt; std::endl;\r\n  }\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  showMe(5.5);          <span style=\"color: #008000;\">\/\/ not showMe&lt;double&gt;(5.5);<\/span>\r\n  showMe(5);            <span style=\"color: #008000;\">\/\/ not showMe&lt;int&gt;(5);<\/span>\r\n    \r\n  ShowMe&lt;<span style=\"color: #2b91af;\">double<\/span>&gt;(5.5);  <span style=\"color: #008000;\">\/\/ with C++17: ShowMe(5.5);<\/span>\r\n  ShowMe&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;(5);       <span style=\"color: #008000;\">\/\/ with C++17: ShowMe(5);<\/span>\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>Line 11 and 22 are possible in C++ since the first C++ standard. Lines 24 and 25 will be possible with C++17. Hence, you do not have to use angle brackets to instantiate a class template.<\/p>\n<p>There is not just usability. Additionally, we will get performance features.<\/p>\n<h4>Guaranteed copy elision<\/h4>\n<p><strong><a href=\"https:\/\/en.wikipedia.org\/wiki\/Return_value_optimization\">RVO<\/a><\/strong> stands for <strong>R<\/strong>eturn <strong>V<\/strong>alue <strong>O<\/strong>ptimisation and means that the compiler is allowed to remove unnecessary copy operations. What was until now a possible optimization step becomes in C++17 a guarantee.<\/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\n2\r\n3\r\n4<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">MyType func(){\r\n  <span style=\"color: #0000ff;\">return<\/span> MyType{};         <span style=\"color: #008000;\">\/\/ no copy with C++17<\/span>\r\n}\r\nMyType myType = func();    <span style=\"color: #008000;\">\/\/ no copy with C++17<\/span>\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Two unnecessary copy operations can happen in these few lines. The first one is in line 2 and the second one is in line 4. With C++17, both copy operations must go.&nbsp;<\/p>\n<p>If the return value has a name, we call it <strong>NRVO.<\/strong> Maybe, you guessed it. This acronym stands for<strong> N<\/strong>amed <strong>R<\/strong>eturn <strong>V<\/strong>alue <strong>O<\/strong>ptimization.<\/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\n2\r\n3\r\n4\r\n5<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">MyType func(){\r\n  MyType myVal;\r\n  <span style=\"color: #0000ff;\">return<\/span> myVal;            <span style=\"color: #008000;\">\/\/ one copy allowed <\/span>\r\n}\r\nMyType myType = func();    <span style=\"color: #008000;\">\/\/ no copy with C++17<\/span>\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The subtle difference is that the compiler can still copy the value <span style=\"font-family: courier new,courier;\">myValue&nbsp;<\/span>according to C++17 (line 3). But no copy will take place in line 5.<span style=\"font-family: courier new,courier;\"><br \/><\/span><\/p>\n<p>If a feature is unnecessary or its application is even dangerous, you should remove it. This will happen in C++17 with <span style=\"font-family: courier new,courier;\">std::auto_ptr<\/span> and trigraphs.<\/p>\n<h4>auto_ptr and trigraphs removed<\/h4>\n<h5>auto_ptr<\/h5>\n<p><span style=\"font-family: courier new,courier;\">std::auto_ptr<\/span> is the first smart pointer in C++. Its job is to take care of one resource. But it had a big issue. If you copy a <span style=\"font-family: courier new,courier;\">std::auto_ptr,<\/span> a move operation will occur under the hood. That is the reason we get <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span> with C++11 as the replacement. You can not copy a <span style=\"font-family: courier new,courier;\">std::unique_ptr. <br \/><\/span><\/p>\n<p>&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\n2\r\n3\r\n4\r\n5\r\n6<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">std::auto_ptr&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; ap1(<span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #2b91af;\">int<\/span>(2011));\r\nstd::auto_ptr&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; ap2= ap1;              <span style=\"color: #008000;\">\/\/ OK     (1)<\/span>\r\n\r\nstd::unique_ptr&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; up1(<span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #2b91af;\">int<\/span>(2011));\r\nstd::unique_ptr&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; up2= up1;            <span style=\"color: #008000;\">\/\/ ERROR  (2)<\/span>\r\nstd::unique_ptr&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; up3= std::move(up1); <span style=\"color: #008000;\">\/\/ OK     (3)<\/span>\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<h5>Trigraphs<\/h5>\n<p>Trigraphs are a sequence of three characters in the source code that are treated as a single character. They will be necessary if your keyboard doesn&#8217;t support single characters.<\/p>\n<p>If you want to write obfuscated code, C++17 maybe not be your language anymore.<\/p>\n<p>&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\n2\r\n3\r\n4\r\n5\r\n6\r\n7<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ trigraphs.cpp<\/span>\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main()??&lt;\r\n\r\n  ??(??)??&lt;??&gt;();\r\n\r\n??&gt;\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I guess, you know, what the program is doing? If not, you have to translate the trigraphs to their single-character representation.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5226\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/trigraph.png\" alt=\"trigraph\" width=\"200\" height=\"315\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/trigraph.png 266w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/trigraph-190x300.png 190w\" sizes=\"auto, (max-width: 200px) 100vw, 200px\" \/><\/p>\n<p>If you apply the table, you will solve the riddle. The program represents a lambda function that will be executed just in place.<\/p>\n<p>&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\n2\r\n3\r\n4\r\n5\r\n6\r\n7<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ trigraphsLambda.cpp<\/span>\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  []{}();\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>That is easy. In the next post, I will write about the library feature we get with C++17. These are the <span style=\"font-family: courier new,courier;\">string_view,<\/span> the parallel STL, and the filesystem library. Additionally, we will get the new data types <span style=\"font-family: courier new,courier;\">std::any, std::optional,<\/span> and <span style=\"font-family: courier new,courier;\">std::variant.<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>C++11, C++14, and C++17. I guess you see the pattern.&nbsp; Later this year, we will get a new C++ standard. In March 2017, the C++17 specification reached the Draft International Standard stage. Before I dive into the details, I will give you an overview of C++17.<\/p>\n","protected":false},"author":21,"featured_media":4724,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[370],"tags":[],"class_list":["post-5227","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-17"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5227","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=5227"}],"version-history":[{"count":0,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5227\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/4724"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5227"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5227"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5227"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}