{"id":5323,"date":"2017-09-29T18:55:05","date_gmt":"2017-09-29T18:55:05","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-function-objects-and-lambas\/"},"modified":"2023-06-26T12:05:36","modified_gmt":"2023-06-26T12:05:36","slug":"c-core-guidelines-function-objects-and-lambas","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-function-objects-and-lambas\/","title":{"rendered":"C++ Core Guidelines: Function Objects and Lambdas"},"content":{"rendered":"<p>I can not think about modern C++ without lambda expressions. So my wrong assumption was that there are many rules for lambda expressions. Wrong! There are fewer than ten rules. But as ever I learned something new.<\/p>\n<p><!--more--><\/p>\n<p>Here are the first four rules for lambda expressions (short lambdas).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" alignright size-full wp-image-5321\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/Lambda.jpg\" alt=\"Lambda\" width=\"200\" height=\"443\" style=\"float: right;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/Lambda.jpg 335w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/Lambda-135x300.jpg 135w\" sizes=\"auto, (max-width: 200px) 100vw, 200px\" \/><\/p>\n<h2>Function objects and lambdas<\/h2>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-capture-vs-overload\">F.50: Use a lambda when a function won\u2019t do (to capture local variables, or to write a local function)<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-reference-capture\">F.52: Prefer capturing by reference in lambdas that will be used locally, including passed to algorithms<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-value-capture\">F.53: Avoid capturing by reference in lambdas that will be used nonlocally, including returned, stored on the heap, or passed to another thread<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Res-lambda-init\">ES.28: Use lambdas for complex initialization, especially of <code class=\"highlighter-rouge no-highlight\">const<\/code> variables<\/a><\/li>\n<\/ul>\n<p>I said I wanted to write about lambda functions. Maybe you are surprised that the headline is called function objects and lambdas. If you know that lambdas are just function objects automatically created by the compiler, then this will not surprise you. If you don&#8217;t know, read the following section because knowing this magic helps a lot in getting a deeper understanding of lambda expressions.&nbsp;<\/p>\n<p>I will make it short because I plan to write about lambda expressions.<\/p>\n<h3>Lambda functions under the hood<\/h3>\n<p>First, a function object is an instance of a class, for which the call operator ( <span style=\"font-family: courier new,courier;\">operator()<\/span> ) is overloaded. This means that a function object is an object that behaves like a function. The main difference between a function and a function object is: a function object is an object and can, therefore, have stated.<\/p>\n<p>Here is a simple example.<\/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;\">int<\/span> <span style=\"color: #cc00ff;\">addFunc<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> a, <span style=\"color: #007788; font-weight: bold;\">int<\/span> b){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> a <span style=\"color: #555555;\">+<\/span> b; }\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\n    <span style=\"color: #006699; font-weight: bold;\">struct<\/span> AddObj{\r\n        <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span>()(<span style=\"color: #007788; font-weight: bold;\">int<\/span> a, <span style=\"color: #007788; font-weight: bold;\">int<\/span> b) <span style=\"color: #006699; font-weight: bold;\">const<\/span> { <span style=\"color: #006699; font-weight: bold;\">return<\/span> a <span style=\"color: #555555;\">+<\/span> b; }\r\n    };\r\n    \r\n    AddObj addObj;\r\n    addObj(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>) <span style=\"color: #555555;\">==<\/span> addFunc(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>);<br \/>\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Instances of the struct <span style=\"font-family: courier new,courier;\">AddObj<\/span> and the function <span style=\"font-family: courier new,courier;\">addFunc<\/span> are both callables.&nbsp; I defined the struct <span style=\"font-family: courier new,courier;\">AddObj<\/span> just in place. The C++ compiler implicitly does that if I use a lambda expression.<\/p>\n<p>Have a look.<\/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;\">int<\/span> <span style=\"color: #cc00ff;\">addFunc<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> a, <span style=\"color: #007788; font-weight: bold;\">int<\/span> b){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> a <span style=\"color: #555555;\">+<\/span> b; }\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> addObj <span style=\"color: #555555;\">=<\/span> [](<span style=\"color: #007788; font-weight: bold;\">int<\/span> a, <span style=\"color: #007788; font-weight: bold;\">int<\/span> b){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> a <span style=\"color: #555555;\">+<\/span> b; };\r\n    \r\n    addObj(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>) <span style=\"color: #555555;\">==<\/span> addFunc(<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>);\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><strong>That&#8217;s all!<\/strong> If the lambda expression captures its environment and therefore has state, the corresponding struct <span style=\"font-family: courier new,courier;\">AddOb<\/span>j gets a constructor for initializing its members. If the lambda expression captures its argument by reference, so does the constructor. The same holds for capturing by value.<\/p>\n<p>With C++14, we have generic lambdas; therefore, you can define a lambda expression such as <span style=\"font-family: courier new,courier;\">[](auto a, auto b){ return a + b; };. <\/span>What does that mean for the call operator of <span style=\"font-family: courier new,courier;\">AddObj<\/span>? I assume you can already guess it. The call operator becomes a template. I want to emphasize it explicitly: <strong>a generic lambda is a function template<\/strong>.&nbsp;<span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<p>I hope this section was not too concise. Let&#8217;s continue with the four rules.<\/p>\n<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-capture-vs-overload\">F.50: Use a lambda when a function won\u2019t do (to capture local variables, or to write a local function)<\/a><\/h3>\n<p>The difference in the usage of functions and lambda functions boils down to two points.&nbsp;<span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<ol>\n<li>You can not overload lambdas.<\/li>\n<li>A lambda function can capture local variables.<\/li>\n<\/ol>\n<p>Here is a contrived example of the second point.<\/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;functional&gt;<\/span>\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>function<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span>)<span style=\"color: #555555;\">&gt;<\/span> makeLambda(<span style=\"color: #007788; font-weight: bold;\">int<\/span> a){    \/\/ (1)\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> [a](<span style=\"color: #007788; font-weight: bold;\">int<\/span> b){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> a <span style=\"color: #555555;\">+<\/span> b; };\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main(){\r\n    \r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> add5 <span style=\"color: #555555;\">=<\/span> makeLambda(<span style=\"color: #ff6600;\">5<\/span>);                \/\/ (2)\r\n    \r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> add10 <span style=\"color: #555555;\">=<\/span> makeLambda(<span style=\"color: #ff6600;\">10<\/span>);              \/\/ (3)\r\n    \r\n    add5(<span style=\"color: #ff6600;\">10<\/span>) <span style=\"color: #555555;\">==<\/span> add10(<span style=\"color: #ff6600;\">5<\/span>);                     \/\/ (4)\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The function<span style=\"font-family: courier new,courier;\"> makeLambda<\/span> returns a lambda expression. The lambda expression takes an <span style=\"font-family: courier new,courier;\">int<\/span> and returns an<span style=\"font-family: courier new,courier;\"> int<\/span>. &nbsp;This is the type of the polymorph function wrapper<span style=\"font-family: courier new,courier;\"> std::function: std::function&lt;int(int)&gt;. <span style=\"font-family: andale mono,times;\">(1).<\/span><\/span> Invoking <span style=\"font-family: courier new,courier;\">makeLambda(5)<\/span> (2) creates a lambda expression that captures <span style=\"font-family: courier new,courier;\">a, <\/span>which is, in this case, 5. The same argumentation holds for makeLambda(10) (3); therefore <span style=\"font-family: courier new,courier;\">add5(10)<\/span> and <span style=\"font-family: courier new,courier;\">add10(5)<\/span> are 15 (4).<span style=\"font-family: courier new,courier;\"><span style=\"font-family: andale mono,times;\"><br \/><\/span><\/span><\/p>\n<p>The next two rules are explicitly dealing with capturing by reference. Both are pretty similar; therefore, I will present them together.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-reference-capture\">F.52: Prefer capturing by reference in lambdas that will be used locally, including passed to algorithms, <\/a><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rf-value-capture\">F.53: Avoid capturing by reference in lambdas that will be used nonlocally, including returned, stored on the heap, or passed to another thread<\/a><\/h3>\n<p>For efficiency and correctness reasons, your lambda expression should capture its variables by reference if the lambda expression is locally used. Accordingly, if the lambda expression is not used locally, you should copy the arguments and not capture the variables by reference. If you break the last statement, you will get undefined behavior.<\/p>\n<p>Here is an example of undefined behavior with lambda expressions.<\/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: #0099ff; font-style: italic;\">\/\/ lambdaCaptureReference.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;functional&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>function<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span>)<span style=\"color: #555555;\">&gt;<\/span> makeLambda(<span style=\"color: #007788; font-weight: bold;\">int<\/span> a){\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> local <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2<\/span> <span style=\"color: #555555;\">*<\/span> a;\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> lam <span style=\"color: #555555;\">=<\/span> [<span style=\"color: #555555;\">&amp;<\/span>local](<span style=\"color: #007788; font-weight: bold;\">int<\/span> b){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> local <span style=\"color: #555555;\">+<\/span> b; };           <span style=\"color: #0099ff; font-style: italic;\">\/\/ 1<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"lam(5): \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>  lam(<span style=\"color: #ff6600;\">5<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;            <span style=\"color: #0099ff; font-style: italic;\">\/\/ 2<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> lam;\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> local <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">10<\/span>;\r\n    \r\n  <span style=\"color: #006699; font-weight: bold;\">auto<\/span> addLocal <span style=\"color: #555555;\">=<\/span> [<span style=\"color: #555555;\">&amp;<\/span>local](<span style=\"color: #007788; font-weight: bold;\">int<\/span> b){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> local <span style=\"color: #555555;\">+<\/span> b; };        <span style=\"color: #0099ff; font-style: italic;\">\/\/ 3<\/span>\r\n    \r\n  <span style=\"color: #006699; font-weight: bold;\">auto<\/span> add10 <span style=\"color: #555555;\">=<\/span> makeLambda(<span style=\"color: #ff6600;\">5<\/span>);\r\n    \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"addLocal(5): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> addLocal(<span style=\"color: #ff6600;\">5<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;    <span style=\"color: #0099ff; font-style: italic;\">\/\/ 4<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"add10(5): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> add10(<span style=\"color: #ff6600;\">5<\/span>) <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;          <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}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The lambda addLocal (3) definition and its usage (4) is fine. The same holds for the definition of the lambda expression <span style=\"font-family: courier new,courier;\">lam<\/span> (1) and its usage (2) inside the function. The undefined behavior is that the function <span style=\"font-family: courier new,courier;\">makeLambda<\/span> returns a lambda expression referencing the local variable <span style=\"font-family: courier new,courier;\">local.<\/span><\/p>\n<p>And guess what value the call <span style=\"font-family: courier new,courier;\">add10(5)<\/span> will have inline (5)? Here we are.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5322\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/LambdaCaptureReference.png\" alt=\"LambdaCaptureReference\" width=\"535\" height=\"455\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/LambdaCaptureReference.png 535w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/LambdaCaptureReference-300x255.png 300w\" sizes=\"auto, (max-width: 535px) 100vw, 535px\" \/><\/p>\n<p>Each execution of the program gives a different result for the expression (5).<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Res-lambda-init\">ES.28: Use lambdas for complex initialization, especially of <code class=\"highlighter-rouge no-highlight\">const<\/code> variables<\/a><\/h3>\n<p>I like this rule because it makes your code more robust. Why do the guidelines call the following program bad?<\/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%;\">widget x;   <span style=\"color: #0099ff; font-style: italic;\">\/\/ should be const, but:<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2<\/span>; i <span style=\"color: #555555;\">&lt;=<\/span> N; <span style=\"color: #555555;\">++<\/span>i) {             <span style=\"color: #0099ff; font-style: italic;\">\/\/ this could be some<\/span>\r\n    x <span style=\"color: #555555;\">+=<\/span> some_obj.do_something_with(i);  <span style=\"color: #0099ff; font-style: italic;\">\/\/ arbitrarily long code<\/span>\r\n}                                        <span style=\"color: #0099ff; font-style: italic;\">\/\/ needed to initialize x<\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ from here, x should be const, but we can't say so in code in this style<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Conceptually, you only want to initialize <span style=\"font-family: courier new,courier;\">widget x.<\/span> If it is initialized, it should stay constant. This is an idea we can not express in C++. If <span style=\"font-family: courier new,courier;\">widget x<\/span> is used in a multithreading program, you have to synchronize it.<\/p>\n<p>This synchronization would not be necessary if <span style=\"font-family: courier new,courier;\">widget x<\/span> were constant. Here is the excellent pendant with lambda expressions.<\/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;\">const<\/span> widget x <span style=\"color: #555555;\">=<\/span> [<span style=\"color: #555555;\">&amp;<\/span>]{\r\n    widget val;                                <span style=\"color: #0099ff; font-style: italic;\">\/\/ assume that widget has a default constructor<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2<\/span>; i <span style=\"color: #555555;\">&lt;=<\/span> N; <span style=\"color: #555555;\">++<\/span>i) {            <span style=\"color: #0099ff; font-style: italic;\">\/\/ this could be some<\/span>\r\n        val <span style=\"color: #555555;\">+=<\/span> some_obj.do_something_with(i);  <span style=\"color: #0099ff; font-style: italic;\">\/\/ arbitrarily long code<\/span>\r\n    }                                          <span style=\"color: #0099ff; font-style: italic;\">\/\/ needed to initialize x<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> val;\r\n}();\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Thanks to the in-place executed lambda, you can define the <span style=\"font-family: courier new,courier;\">widget x<\/span> as a constant. You can not change its value; therefore, you can use it in a multithreading program without expensive synchronization.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>One of the critical characteristics of object orientation is inheritance. The C++ Core Guidelines have roughly 25 rules for class hierarchies. In the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-class-hierarchies\">next post<\/a>, I will write about the concepts of interfaces and implementations in class hierarchies.<\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I can not think about modern C++ without lambda expressions. So my wrong assumption was that there are many rules for lambda expressions. Wrong! There are fewer than ten rules. But as ever I learned something new.<\/p>\n","protected":false},"author":21,"featured_media":5321,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[499,459],"class_list":["post-5323","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-classes","tag-lambdas"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5323","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=5323"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5323\/revisions"}],"predecessor-version":[{"id":6858,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5323\/revisions\/6858"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5321"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5323"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}