{"id":5255,"date":"2017-05-07T20:20:57","date_gmt":"2017-05-07T20:20:57","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-17-the-improved-interface-of-the-associative-containers\/"},"modified":"2023-06-26T12:17:04","modified_gmt":"2023-06-26T12:17:04","slug":"c-17-the-improved-interface-of-the-associative-containers","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-17-the-improved-interface-of-the-associative-containers\/","title":{"rendered":"C++17: Improved Associative Containers and Uniform Container Access"},"content":{"rendered":"<p>C++11 has eight associative containers. With C++17, you can more comfortably insert new elements into them, merge existing associative containers, or move elements from one container into another if they are similar. But that is not all. The access to the associative and sequential containers was unified.<\/p>\n<p><!--more--><\/p>\n<p>Before I dive into the details, let me first answer the question: What do I mean by similar associative containers? We have eight associative containers. Here are they.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5253\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/eightAssociativeContainers.png\" alt=\"\" width=\"600\" height=\"231\" style=\"margin: 15px;\" data-alt=\"eightAssociativeContainers\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/eightAssociativeContainers.png 956w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/eightAssociativeContainers-300x115.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/eightAssociativeContainers-768x296.png 768w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>By similar, I mean their elements have the same structure and data types. The elements of <span style=\"font-family: courier new,courier;\">std::set<\/span> and <span style=\"font-family: courier new,courier;\">std::multiset<\/span>, <span style=\"font-family: courier new,courier;\">std::unordered_set<\/span> and <span style=\"font-family: courier new,courier;\">std::unordered_multiset<\/span>, <span style=\"font-family: courier new,courier;\">std::map<\/span> and <span style=\"font-family: courier new,courier;\">std::multimap<\/span>, and<span style=\"font-family: courier new,courier;\"> std::unordered_map<\/span> and <span style=\"font-family: courier new,courier;\">std::unordered_multimap<\/span> have the same structure.&nbsp;<\/p>\n<p>Of course, that was only a high-level overview of the eight associative containers. That is for two reasons. First, I want to write about the improved interface. Second, you can read the details in my previous post:<a href=\"https:\/\/www.modernescpp.com\/index.php\/hash-tables\"> Hash Tables<\/a>.&nbsp;<\/p>\n<p>Now to something completely new.<\/p>\n<h2>The improved interface of the associative containers<\/h2>\n<p>Let me show you the improved interface with an exhaustive example.<\/p>\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: #0099ff; font-style: italic;\">\/\/ accociativeContainers.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;map&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;utility&gt;<\/span>\r\n \r\n<span style=\"color: #006699; font-weight: bold;\">using<\/span> <span style=\"color: #006699; font-weight: bold;\">namespace<\/span> std<span style=\"color: #555555;\">::<\/span>literals;                                     <span style=\"color: #0099ff; font-style: italic;\">\/\/ 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> Cont<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> printContainer(<span style=\"color: #006699; font-weight: bold;\">const<\/span> Cont<span style=\"color: #555555;\">&amp;<\/span> cont, <span style=\"color: #006699; font-weight: bold;\">const<\/span> std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&amp;<\/span> mess){    <span style=\"color: #0099ff; font-style: italic;\">\/\/ 2<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> mess;\r\n  <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">auto<\/span><span style=\"color: #555555;\">&amp;<\/span> pa<span style=\"color: #555555;\">:<\/span> cont){\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"(\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> pa.first <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\": \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> pa.second <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\") \"<\/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<span style=\"color: #007788; font-weight: bold;\">int<\/span> main(){\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>map<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&gt;<\/span> ordMap{{<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #cc3300;\">\"a\"<\/span>s}, {<span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #cc3300;\">\"b\"<\/span>}};          <span style=\"color: #0099ff; font-style: italic;\">\/\/ 3<\/span>\r\n  ordMap.try_emplace(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #cc3300;\">'C'<\/span>);\r\n  ordMap.try_emplace(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #cc3300;\">'c'<\/span>);\r\n \r\n  printContainer(ordMap, <span style=\"color: #cc3300;\">\"try_emplace: \"<\/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  std<span style=\"color: #555555;\">::<\/span>map<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&gt;<\/span> ordMap2{{<span style=\"color: #ff6600;\">3<\/span>, std<span style=\"color: #555555;\">::<\/span>string(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #cc3300;\">'C'<\/span>)},     <span style=\"color: #0099ff; font-style: italic;\">\/\/ 4<\/span>\r\n                                      {<span style=\"color: #ff6600;\">4<\/span>, std<span style=\"color: #555555;\">::<\/span>string(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #cc3300;\">'D'<\/span>)}};\r\n  ordMap2.insert_or_assign(<span style=\"color: #ff6600;\">5<\/span>, std<span style=\"color: #555555;\">::<\/span>string(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #cc3300;\">'e'<\/span>));\r\n  ordMap2.insert_or_assign(<span style=\"color: #ff6600;\">5<\/span>, std<span style=\"color: #555555;\">::<\/span>string(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #cc3300;\">'E'<\/span>));\r\n  \r\n  printContainer(ordMap2, <span style=\"color: #cc3300;\">\"insert_or_assign: \"<\/span>);                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ 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  ordMap.merge(ordMap2);                                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ 6<\/span>\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"ordMap.merge(ordMap2)\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n  \r\n  printContainer(ordMap, <span style=\"color: #cc3300;\">\"  ordMap: \"<\/span>);\r\n  printContainer(ordMap2, <span style=\"color: #cc3300;\">\"  ordMap2: \"<\/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  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"extract and insert: \"<\/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>multimap<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&gt;<\/span> multiMap{{<span style=\"color: #ff6600;\">2017<\/span>, std<span style=\"color: #555555;\">::<\/span>string(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #cc3300;\">'F'<\/span>)}};  \r\n  \r\n  <span style=\"color: #006699; font-weight: bold;\">auto<\/span> nodeHandle <span style=\"color: #555555;\">=<\/span> multiMap.extract(<span style=\"color: #ff6600;\">2017<\/span>);                        <span style=\"color: #0099ff; font-style: italic;\">\/\/ 7<\/span>\r\n  nodeHandle.key() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">6<\/span>;                                           \r\n  ordMap.insert(std<span style=\"color: #555555;\">::<\/span>move(nodeHandle));                         \r\n\r\n  printContainer(ordMap, <span style=\"color: #cc3300;\">\"   ordMap: \"<\/span>);\r\n  printContainer(multiMap, <span style=\"color: #cc3300;\">\"   multiMap: \"<\/span>);\r\n  \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I use in the example a <span style=\"font-family: Courier New,Courier,monospace;\">std::map<\/span> because, most of the time, a <span style=\"font-family: Courier New,Courier,monospace;\">std::map<\/span> is your first choice for an associative container. If your associative container is big and performance is critical, think about a <span style=\"font-family: Courier New,Courier,monospace;\">std::unordered_map<\/span>. In the post <a href=\"https:\/\/www.modernescpp.com\/index.php\/associative-containers-a-simple-performance-comparison\">Associative Containers &#8211; A simple Performance Comparison<\/a> are a few performance numbers.<\/p>\n<p>To simplify my life, I wrote the function template printContainer (2) to display the associative container with a short message. The same argument holds for <span style=\"font-family: courier new,courier;\">using namespace std::literals <\/span>expression (1). Now, I can use the&nbsp;new built-in literal for a C++ string. You see its usage in the key\/value pair <span style=\"font-family: courier new,courier;\">{1, &#8220;a&#8221;s}<\/span> in (3). <span style=\"font-family: courier new,courier;\">&#8220;a&#8221;s<\/span> is the C++ string literal that has been available since C++14. You must add the character <span style=\"font-family: courier new,courier;\">s<\/span> to the C string literal<span style=\"font-family: courier new,courier;\"> &#8220;a&#8221;<\/span> to get a C++ string literal.<\/p>\n<p>Now, I will explain the program in detail. To get a better idea of it, peek at the output.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5254\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/accociativeContainers.png\" alt=\"accociativeContainers\" width=\"500\" height=\"216\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/accociativeContainers.png 543w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/accociativeContainers-300x130.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>There are two new ways to add elements to an associative container: <span style=\"font-family: Courier New,Courier,monospace;\">try_emplace<\/span> and <span style=\"font-family: Courier New,Courier,monospace;\">insert_or_assign<\/span>. <span style=\"font-family: Courier New,Courier,monospace;\">ordMap.try_emplace(3, 3, &#8216;C&#8217;)<\/span> (3) tries to add a new element to <span style=\"font-family: Courier New,Courier,monospace;\">ordMap<\/span>. The first <span style=\"font-family: Courier New,Courier,monospace;\">3<\/span> is the key of the element, and the following <code>3<\/code> and <span style=\"font-family: Courier New,Courier,monospace;\">&#8216;C&#8217;<\/span> directly go to the constructor of the value, which is, in this case, a <span style=\"font-family: Courier New,Courier,monospace;\">std::string<\/span>. It&#8217;s called try. Therefore, if the key is already in the <span style=\"font-family: courier new,courier;\">std::map<\/span>, nothing happens.<span style=\"font-family: Courier New,Courier,monospace;\"> ordMap2.insert_or_assign(5, std::string(3, &#8216;e&#8217;))<\/span> (4) behaves different. The first call (4) inserts the key\/value pair <span style=\"font-family: Courier New,Courier,monospace;\">5<\/span>, <span style=\"font-family: Courier New,Courier,monospace;\">std::string(&#8220;eee&#8221;)<\/span>, and the second call assigns the <span style=\"font-family: Courier New,Courier,monospace;\">std::string(&#8220;EEE&#8221;)<\/span> to the key<span style=\"font-family: Courier New,Courier,monospace;\"> 5<\/span>.<\/p>\n<p>With C++17, you can merge associative Containers (6). <span style=\"font-family: Courier New,Courier,monospace;\">ordMap.merge(ordMap2)<\/span> will merge the associative container<span style=\"font-family: Courier New,Courier,monospace;\"> ordMap2 <\/span>into <span style=\"font-family: Courier New,Courier,monospace;\">ordMap<\/span>. Formally this process is called &#8220;splice&#8221;. That means each node consisting of the key\/value pair will be extracted from<span style=\"font-family: Courier New,Courier,monospace;\"> ordMap2<\/span> and inserted into <span style=\"font-family: Courier New,Courier,monospace;\">ordMap<\/span> if the key is unavailable in <span style=\"font-family: Courier New,Courier,monospace;\">ordMap<\/span>. If the key is already in <span style=\"font-family: Courier New,Courier,monospace;\">ordMap<\/span>, nothing will happen. There is no copy or move operation involved. All pointers and references to the transferred node remain valid.&nbsp; You can merge nodes between similar containers. Associative containers must have the same structure and the same data types.<\/p>\n<p>The extracting and inserting goes on (7). As mentioned, each associative container has a new subtype: <span style=\"font-family: Courier New,Courier,monospace;\">node_type<\/span>. I implicitly used it by merging one container into another (6). You can even use the <span style=\"font-family: Courier New,Courier,monospace;\">no<\/span>de_type to change a key of a key\/value pair. Have a look here.<span style=\"font-family: Courier New,Courier,monospace;\"> auto nodeHandle multiMap.extract(2017)<\/span> extracts the node with the key 2017 from the <span style=\"font-family: Courier New,Courier,monospace;\">std::multimap&lt;int, std::string&gt;<\/span>. In the following lines, I change the key to 6:<span style=\"font-family: Courier New,Courier,monospace;\"> nodeHandle.key() = 6<\/span> and insert it into <span style=\"font-family: Courier New,Courier,monospace;\">ordMap<\/span>. I have to move the node, and copying is not possible.<\/p>\n<p>Of course, I also can insert the node into the same associative container (A) from which I extracted it or insert the node into the <span style=\"font-family: Courier New,Courier,monospace;\">ordMap<\/span> without changing the key (B). You can also change the value of node (C).<\/p>\n<p>&nbsp;<\/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;\">auto<\/span> nodeHandle <span style=\"color: #555555;\">=<\/span> multiMap.extract(<span style=\"color: #ff6600;\">2017<\/span>);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ A                      <\/span>\r\nnodeHandle.key() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">6<\/span>;\r\nmultiMap.insert(std<span style=\"color: #555555;\">::<\/span>move(nodeHandle));\r\n  \r\n\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> nodeHandle <span style=\"color: #555555;\">=<\/span> multiMap.extract(<span style=\"color: #ff6600;\">2017<\/span>);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ B                     <\/span>\r\nordMap.insert(std<span style=\"color: #555555;\">::<\/span>move(nodeHandle)); \r\n\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> nodeHandle <span style=\"color: #555555;\">=<\/span> multiMap.extract(<span style=\"color: #ff6600;\">2017<\/span>);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ C<\/span>\r\nnodeHandle.key() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">6<\/span>;\r\nordMap.insert(std<span style=\"color: #555555;\">::<\/span>move(nodeHandle));   \r\nordMap[<span style=\"color: #ff6600;\">6<\/span>] <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>string(<span style=\"color: #cc3300;\">\"ZZZ\"<\/span>);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>If you extract&nbsp;a node from an associative container (A) having a value such as <span style=\"font-family: courier new,courier;\">std::map<\/span>, <span style=\"font-family: courier new,courier;\">std::unordered_map<\/span>, <span style=\"font-family: courier new,courier;\">std::multimap<\/span>, or <span style=\"font-family: courier new,courier;\">std::unordered_multimap<\/span>, you get a node <span style=\"font-family: courier new,courier;\">nodeHandleMap<\/span>, on which you can invoke <span style=\"font-family: courier new,courier;\">nodeHandleMap.key()<\/span>. There is no method <span style=\"font-family: courier new,courier;\">nodeHandleMap.value() <\/span>to change the node&#8217;s value. Curiously enough, if you extract a node <span style=\"font-family: courier new,courier;\">nodeHandleSet<\/span> from a <span style=\"font-family: courier new,courier;\">std::set<\/span> or one of its three siblings, you can change the key by invoking <span style=\"font-family: courier new,courier;\">nodeHandleSet.value()<\/span>.<\/p>\n<p>&nbsp;C++17 get three new global functions for accessing a container.<\/p>\n<\/p>\n<h2>Uniform container access<\/h2>\n<p>The three new functions are named<span style=\"font-family: courier new,courier;\"> std::size, std::empty,<\/span> and <span style=\"font-family: courier new,courier;\">std::data<\/span>.<\/p>\n<ul>\n<li><span style=\"font-family: courier new,courier;\">std::size: <\/span>Returns the size of a STL container, a C++ string, or a C array.<\/li>\n<li><span style=\"font-family: courier new,courier;\">std::empty: <\/span>Returns whether a given STL container, a C++ string, o a C array is empty.<\/li>\n<li><span style=\"font-family: courier new,courier;\">std::data: <\/span>Returns a pointer to the block of memory containing the elements of a container. The container has to have method data. This holds true for a <span style=\"font-family: courier new,courier;\">std::vector<\/span>, a <span style=\"font-family: courier new,courier;\">std::string<\/span>, and a <span style=\"font-family: courier new,courier;\">std::array<\/span>.&nbsp;<\/li>\n<\/ul>\n<h2>What&#8217;s next?<\/h2>\n<p>I have written about 10 posts on C++17. Here are they: <a href=\"https:\/\/www.modernescpp.com\/index.php\/category\/c-17\">category C++17<\/a>. Therefore, I&#8217;m done. I have written the last two years a lot of posts about multithreading. These posts were about the<a href=\"https:\/\/www.modernescpp.com\/index.php\/category\/multithreading\"> theory<\/a>, the <a href=\"https:\/\/www.modernescpp.com\/index.php\/category\/multithreading-application\">practice<\/a>, <a href=\"https:\/\/www.modernescpp.com\/index.php\/category\/multithreading-c-17-and-c-20\">concurrency with C++17 and C++20<\/a>, and the <a href=\"https:\/\/www.modernescpp.com\/index.php\/category\/multithreading-memory-model\">memory model<\/a>. As you might guess, I have a few new posts in mind for wrapping up&nbsp;my previous posts. Therefore, I will write my <a href=\"https:\/\/www.modernescpp.com\/index.php\/race-condition-versus-data-race\">next posts<\/a> about multithreading in existing and concurrency in the upcoming C++ standards. First, I have to define a few terms. So I will write about data race versus race conditions. In German, we use the term &#8220;kritischer Wettlauf&#8221; for two different phenomena. That is extremely bad. Because in concurrency, concise terminology is critical.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>C++11 has eight associative containers. With C++17, you can more comfortably insert new elements into them, merge existing associative containers, or move elements from one container into another if they are similar. But that is not all. The access to the associative and sequential containers was unified.<\/p>\n","protected":false},"author":21,"featured_media":5253,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[370],"tags":[472],"class_list":["post-5255","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-17","tag-associative-containers"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5255","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=5255"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5255\/revisions"}],"predecessor-version":[{"id":6873,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5255\/revisions\/6873"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5253"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5255"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5255"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}