{"id":5363,"date":"2017-12-23T07:26:22","date_gmt":"2017-12-23T07:26:22","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-passing-smart-pointer\/"},"modified":"2023-06-26T12:00:05","modified_gmt":"2023-06-26T12:00:05","slug":"c-core-guidelines-passing-smart-pointer","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-passing-smart-pointer\/","title":{"rendered":"C++ Core Guidelines: Passing Smart Pointers"},"content":{"rendered":"<p>Passing smart pointers is a critical topic that is seldom addressed. This ends with the C++ core guidelines because they have six rules for passing <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> and <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span>.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5362\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/12\/relay-race.png\" alt=\"relay race\" width=\"640\" height=\"426\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/12\/relay-race.png 640w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/12\/relay-race-300x200.png 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/p>\n<p>The six rules violate the import dry (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Don%27t_repeat_yourself\">don&#8217;t repeat yourself<\/a>) principle for software development. Ultimately, we have only four rules that make our life as software developers much easier. Here are the rules.<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-uniqueptrparam\">R.32: Take a <code class=\"highlighter-rouge no-highlight\">unique_ptr&lt;widget&gt;<\/code> parameter to express that a function assumes ownership of a <code class=\"highlighter-rouge no-highlight\">widget<\/code><\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-reseat\">R.33: Take a <code class=\"highlighter-rouge no-highlight\">unique_ptr&lt;widget&gt;&amp;<\/code> parameter to express that a function reseats the <code class=\"highlighter-rouge no-highlight\">widget<\/code><\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-sharedptrparam-owner\">R.34: Take a <code class=\"highlighter-rouge no-highlight\">shared_ptr&lt;widget&gt;<\/code> parameter to express that a function is part owner<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-sharedptrparam\">R.35: Take a <code class=\"highlighter-rouge no-highlight\">shared_ptr&lt;widget&gt;&amp;<\/code> parameter to express that a function might reseat the shared pointer<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-sharedptrparam-const\">R.36: Take a <code class=\"highlighter-rouge no-highlight\">const shared_ptr&lt;widget&gt;&amp;<\/code> parameter to express that it might retain a reference count to the object ???<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-smartptrget\">R.37: Do not pass a pointer or reference obtained from an aliased smart pointer<\/a><\/li>\n<\/ul>\n<p>&nbsp;Let&#8217;s start with the first two rules for <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span>.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-uniqueptrparam\">R.32: Take a <code class=\"highlighter-rouge no-highlight\">unique_ptr&lt;widget&gt;<\/code> parameter to express that a function assumes ownership of a <code class=\"highlighter-rouge no-highlight\">widget<\/code><\/a><\/h3>\n<p>If a function should take ownership of a <span style=\"font-family: courier new,courier;\">Widget,<\/span> you should take the <span style=\"font-family: courier new,courier;\">std::unique_ptr&lt;Widget&gt;<\/span> by copy. The consequence is that the caller has to move the <span style=\"font-family: courier new,courier;\">std::unique_ptr&lt;Widget&gt; <\/span>to make the code run.<\/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: #009999;\">#include &lt;memory&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;utility&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Widget{\r\n    Widget(<span style=\"color: #007788; font-weight: bold;\">int<\/span>){}\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">sink<\/span>(std<span style=\"color: #555555;\">::<\/span>unique_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;<\/span> uniqPtr){\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ do something with uniqPtr<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> uniqPtr <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_unique<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">1998<\/span>);\r\n    \r\n    sink(std<span style=\"color: #555555;\">::<\/span>move(uniqPtr));      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n    sink(uniqPtr);                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2) ERROR<\/span>\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Call (1) is fine, but call (2) breaks because you can not copy a <span style=\"font-family: courier new,courier;\">std::unique_ptr.<\/span> If your function only wants to use the <span style=\"font-family: courier new,courier;\">Widget,<\/span> it should take its parameter by the pointer or reference. The difference between a pointer and a reference is that a pointer can be a null pointer.<span style=\"font-family: courier new,courier;\"><\/span><span style=\"font-family: courier new,courier;\"><\/span><span style=\"font-family: courier new,courier;\"><\/span><\/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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">useWidget<\/span>(Widget<span style=\"color: #555555;\">*<\/span> wid);\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">useWidget<\/span>(Widget<span style=\"color: #555555;\">&amp;<\/span> wid);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-reseat\">R.33: Take a <code class=\"highlighter-rouge no-highlight\">unique_ptr&lt;widget&gt;&amp;<\/code> parameter to express that a function reseats the <code class=\"highlighter-rouge no-highlight\">widget<\/code><\/a><\/h3>\n<p>Sometimes a function wants to reseat a <span style=\"font-family: courier new,courier;\">Widget.<\/span> In this use case, you should pass the <span style=\"font-family: courier new,courier;\">std::unique_ptr&lt;Widget&gt;<\/span> by a non-const reference.<\/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: #009999;\">#include &lt;memory&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;utility&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Widget{\r\n    Widget(<span style=\"color: #007788; font-weight: bold;\">int<\/span>){}\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">reseat<\/span>(std<span style=\"color: #555555;\">::<\/span>unique_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;&amp;<\/span> uniqPtr){\r\n    uniqPtr.reset(<span style=\"color: #006699; font-weight: bold;\">new<\/span> Widget(<span style=\"color: #ff6600;\">2003<\/span>));   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (0)<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ do something with uniqPtr<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> uniqPtr <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_unique<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">1998<\/span>);\r\n    \r\n    reseat(std<span style=\"color: #555555;\">::<\/span>move(uniqPtr));       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1) ERROR<\/span>\r\n    reseat(uniqPtr);                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2) <\/span>\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Now, the call (1) fails because you can not bind an rvalue to a non-const lvalue reference. This will not hold for the copy in (2). A lvalue can be bound to an lvalue reference. By the way. The call (0) will not only construct a new <span style=\"font-family: courier new,courier;\">Widget(2003<\/span>), but it will also destroy the old <span style=\"font-family: courier new,courier;\">Widget(1998)<\/span>.<\/p>\n<p>The next three rules to <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> are repetitions; therefore, I will make one out of them.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-sharedptrparam-owner\">R.34: Take a <code class=\"highlighter-rouge no-highlight\">shared_ptr&lt;widget&gt;<\/code> parameter to express that a function is part owner<\/a>, <a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-sharedptrparam\">R.35: Take a <code class=\"highlighter-rouge no-highlight\">shared_ptr&lt;widget&gt;&amp;<\/code> parameter to express that a function might reseat the shared pointer,&nbsp; <\/a>and <a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-sharedptrparam-const\">R.36: Take a <code class=\"highlighter-rouge no-highlight\">const shared_ptr&lt;widget&gt;&amp;<\/code> parameter to express that it might retain a reference count to the object ???<\/a><\/h3>\n<p>Here are the three function signatures we have to deal with.<\/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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">share<\/span>(std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;<\/span> shaWid);\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">reseat<\/span>(std<span style=\"color: #555555;\">::<\/span>shard_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;&amp;<\/span> shadWid);\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">mayShare<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;&amp;<\/span> shaWid);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Let&#8217;s look at each function signature in isolation. What does this mean from the function perspective?<\/p>\n<ul>\n<li><span style=\"font-family: courier new,courier;\"><strong>void share(std::shared_ptr&lt;Widget&gt; shaWid)<\/strong>: <\/span>I&#8217;m for the lifetime of the function body a shared owner of the&nbsp;<span style=\"font-family: courier new,courier;\">Widget.<\/span> At the beginning of the function body, I will increase the reference counter; at the end, I will decrease the reference counter; therefore, the&nbsp;<span style=\"font-family: courier new,courier;\">Widget<\/span> will stay alive as long as I use it.<\/li>\n<li><span style=\"font-family: courier new,courier;\"><strong>void reseat(std::shared_ptr&lt;Widget&gt;&amp; shaWid)<\/strong>: <\/span>I&#8217;m not a shared Widget owner because I will not change the reference counter. I have not guaranteed that the <span style=\"font-family: courier new,courier;\">Widget<\/span> will stay alive during the execution of my function, but I can reseat the resource. A non-const lvalue reference is more like I borrow the resource and can reseat it.&nbsp;<\/li>\n<li><span style=\"font-family: courier new,courier;\"><strong>void mayShare(const std::shared_ptr&lt;Widget&gt;&amp; shaWid)<\/strong>: <\/span>I only borrow the resource. Neither can I extend the resource&#8217;s lifetime nor can I reseat the resource. You should use a pointer (<span style=\"font-family: courier new,courier;\">Widget*)<\/span> or a reference (<span style=\"font-family: courier new,courier;\">Widget&amp;)<\/span> as a parameter instead because there is no added value in using a <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span>. <span style=\"font-family: courier new,courier;\"><br \/><\/span><\/li>\n<\/ul>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-smartptrget\">R.37: Do not pass a pointer or reference obtained from an aliased smart pointer<\/a><\/h3>\n<p>Let me present you with a short code snippet to clarify the rule.<\/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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">oldFunc<\/span>(Widget<span style=\"color: #555555;\">*<\/span> wid){\r\n  <span style=\"color: #0099ff; font-style: italic;\">\/\/ do something with wid<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">shared<\/span>(std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;&amp;<\/span> shaPtr){       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n    \r\n   oldFunc(<span style=\"color: #555555;\">*<\/span>shaPtr);                                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n   \r\n   <span style=\"color: #0099ff; font-style: italic;\">\/\/ do something with shaPtr<\/span>\r\n     \r\n }\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> globShared <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_shared<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">2011<\/span>);   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n\r\n\r\n...\r\n\r\nshared(globShared);                                 <span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>globShared (1) is a globally shared pointer. The function <span style=\"font-family: courier new,courier;\">shared<\/span> takes its argument per reference (2). Therefore, the reference counter of <span style=\"font-family: courier new,courier;\">shaPtr<\/span> will not be increased, and the function share will not extend the lifetime of <span style=\"font-family: courier new,courier;\">Widget(2011)<\/span>. The issue begins with (3). <span style=\"font-family: courier new,courier;\">oldFunc<\/span> accepts a pointer to the <span style=\"font-family: courier new,courier;\">Widget;<\/span> therefore, <span style=\"font-family: courier new,courier;\">oldFunc<\/span> has no guarantee that the <span style=\"font-family: courier new,courier;\">Widget<\/span> will stay alive during its execution. <span style=\"font-family: courier new,courier;\">oldFunc<\/span> only borrows the <span style=\"font-family: courier new,courier;\">Widget.<\/span><\/p>\n<p>The cure is quite simple. You have to ensure that the reference count of <span style=\"font-family: courier new,courier;\">globShared<\/span> will be increased before the call to the function <span style=\"font-family: courier new,courier;\">oldFunc.<\/span> This means you have to make a copy of the <span style=\"font-family: courier new,courier;\">std::shared_ptr:<\/span><\/p>\n<ul>\n<li>Pass the <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> by copying to the function <span style=\"font-family: courier new,courier;\">shared:<\/span><span style=\"font-family: courier new,courier;\"><br \/><\/span> <!-- HTML generated using hilite.me -->\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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">shared<\/span>(std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;<\/span> shaPtr){\r\n   \r\n   oldFunc(<span style=\"color: #555555;\">*<\/span>shaPtr);\r\n   \r\n   <span style=\"color: #0099ff; font-style: italic;\">\/\/ do something with shaPtr<\/span>\r\n     \r\n } \r\n<\/pre>\n<\/div>\n<\/li>\n<li>Make a copy of the <span style=\"font-family: courier new,courier;\">shaPtr<\/span> in the function <span style=\"font-family: courier new,courier;\">shared:<\/span> <!-- HTML generated using hilite.me -->\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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">shared<\/span>(std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;&amp;<\/span> shaPtr){\r\n   \r\n   <span style=\"color: #006699; font-weight: bold;\">auto<\/span> keepAlive <span style=\"color: #555555;\">=<\/span> shaPtr;   \r\n   oldFunc(<span style=\"color: #555555;\">*<\/span>shaPtr);\r\n   \r\n   <span style=\"color: #0099ff; font-style: italic;\">\/\/ do something with keepAlive or shaPtr<\/span>\r\n     \r\n } \r\n<\/pre>\n<\/div>\n<\/li>\n<\/ul>\n<p>The same reasoning also applies to <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span>, but I have no simple cure in mind because you can not copy a <span style=\"font-family: courier new,courier;\">std::unique_ptr.<\/span> I suggest you should clone your <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span> and, therefore, make a new <span style=\"font-family: courier new,courier;\">std::unique_ptr. <\/span><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>This was the last of my four posts about resource management in the C++ core guidelines. The C++ core guidelines have more than 50 rules for expressions and statements. I will have a closer look at <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-expressions-and-statements\">my next <\/a>post.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Passing smart pointers is a critical topic that is seldom addressed. This ends with the C++ core guidelines because they have six rules for passing std::shared_ptr and std::unique_ptr.<\/p>\n","protected":false},"author":21,"featured_media":5362,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[498,399],"class_list":["post-5363","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-memory","tag-smart-pointers"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5363","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=5363"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5363\/revisions"}],"predecessor-version":[{"id":6846,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5363\/revisions\/6846"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5362"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}