{"id":5223,"date":"2017-03-17T20:38:46","date_gmt":"2017-03-17T20:38:46","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/defintion-of-concepts\/"},"modified":"2023-06-26T12:19:13","modified_gmt":"2023-06-26T12:19:13","slug":"defintion-of-concepts","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/defintion-of-concepts\/","title":{"rendered":"Defining Concepts"},"content":{"rendered":"<p>I wrote a<a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/concepts\"> few posts<\/a> about using concepts. Concepts are a named set of requirements. Let&#8217;s define a few concepts in this post.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p>A concept can be defined by a function template or by a variable template. A <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/variable_template\">variable template<\/a> is new with C++14 and declares a family of variables. If you use a function template for your concept, it&#8217;s called a <strong>function concep<\/strong>t; in the second case a <strong>variable concept<\/strong>.<\/p>\n<h2>Two forms<\/h2>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0000ff;\"><br \/>template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\nconcept <span style=\"color: #2b91af;\">bool<\/span> Integral = std::is_integral&lt;T&gt;::value;\r\n}\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\nconcept <span style=\"color: #2b91af;\">bool<\/span> Equal(){\r\n  <span style=\"color: #0000ff;\">return<\/span> requires(T a, T b) {\r\n    { a == b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n    { a != b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n  };\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">Integral<\/span> is a variable concept and <span style=\"font-family: courier new,courier;\">Equal<\/span> is a functional concept. Both return a boolean.<\/p>\n<ul>\n<li>The type parameter T fulfills the variable concept <span style=\"font-family: courier new,courier;\">Integral<\/span> if <span style=\"font-family: courier new,courier;\">std::is_integral&lt;T&gt;::value<\/span> returns <span style=\"font-family: courier new,courier;\">true.<\/span><\/li>\n<li>The type parameter T fulfills the function concept <span style=\"font-family: courier new,courier;\">Equal<\/span> if there are overloaded operators <span style=\"font-family: courier new,courier;\">==<\/span> and<span style=\"font-family: courier new,courier;\"> !=<\/span> for T that returns a boolean.<\/li>\n<\/ul>\n<p>&nbsp;The function concept <span style=\"font-family: courier new,courier;\">Equal<\/span> look very familiar to me. Why? You will see it in a few sentences. But let me first apply the concept.<\/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\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ conceptsDefintionEqual.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\nconcept <span style=\"color: #2b91af;\">bool<\/span> Equal(){\r\n  <span style=\"color: #0000ff;\">return<\/span> requires(T a, T b) {\r\n    { a == b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n    { a != b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n  };\r\n}\r\n\r\n<span style=\"color: #2b91af;\">bool<\/span> areEqual(Equal a, Equal b){\r\n  <span style=\"color: #0000ff;\">return<\/span> a == b;\r\n}\r\n\r\n<span style=\"color: #008000;\">\/*<\/span>\r\n\r\n<span style=\"color: #008000;\">struct WithoutEqual{<\/span>\r\n<span style=\"color: #008000;\">  bool operator==(const WithoutEqual&amp; other) = delete;<\/span>\r\n<span style=\"color: #008000;\">};<\/span>\r\n\r\n<span style=\"color: #008000;\">struct WithoutUnequal{<\/span>\r\n<span style=\"color: #008000;\">  bool operator!=(const WithoutUnequal&amp; other) = delete;<\/span>\r\n<span style=\"color: #008000;\">};<\/span>\r\n\r\n<span style=\"color: #008000;\">*\/<\/span>\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n  \r\n  std::cout &lt;&lt; std::boolalpha &lt;&lt; std::endl;\r\n  \r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"areEqual(1, 5): \"<\/span> &lt;&lt; areEqual(1, 5) &lt;&lt; std::endl;\r\n  \r\n  <span style=\"color: #008000;\">\/*<\/span>\r\n<span style=\"color: #008000;\">  <\/span>\r\n<span style=\"color: #008000;\">  bool res = areEqual(WithoutEqual(),  WithoutEqual());<\/span>\r\n<span style=\"color: #008000;\">  <\/span>\r\n<span style=\"color: #008000;\">  bool res2 = areEqual(WithoutUnequal(),  WithoutUnequal());<\/span>\r\n<span style=\"color: #008000;\">  <\/span>\r\n<span style=\"color: #008000;\">  *\/<\/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>I used the concept <span style=\"font-family: courier new,courier;\">Equal<\/span> in the (generic) function <span style=\"font-family: courier new,courier;\">areEqual<\/span> (lines 13 to 15). That&#8217;s not so exciting. Here is the output of the function <span style=\"font-family: courier new,courier;\">areEqual:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5219\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinition.png\" alt=\"conceptsDefinition\" style=\"margin: 15px;\" width=\"455\" height=\"136\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinition.png 455w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinition-300x90.png 300w\" sizes=\"auto, (max-width: 455px) 100vw, 455px\" \/><\/p>\n<p>What is more interesting is if I use the class <span style=\"font-family: courier new,courier;\">WithoutEqual<\/span> and <span style=\"font-family: courier new,courier;\">WithoutUnequal.<\/span>I set for both the<span style=\"font-family: courier new,courier;\"> ==<\/span> or respectively the <span style=\"font-family: courier new,courier;\">!=<\/span> operator to <span style=\"font-family: courier new,courier;\">delete. <\/span>The compiler complains immediately that both types do not fulfill the concept.<span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5220\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionError.png\" alt=\"conceptsDefinitionError\" width=\"700\" height=\"324\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionError.png 1151w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionError-300x139.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionError-1024x473.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionError-768x355.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p><span style=\"font-family: courier new,courier;\">Equal<\/span> look familiar to me. Now, you see why.<\/p>\n<\/p>\n<h2>The concept Equal and Ord<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5169\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/typeclass.png\" alt=\"typeclass\" style=\"margin: 15px;\" width=\"542\" height=\"460\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/typeclass.png 542w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/02\/typeclass-300x255.png 300w\" sizes=\"auto, (max-width: 542px) 100vw, 542px\" \/><\/p>\n<p>This is part of the type hierarchy of Haskell&#8217;s type classes. You have a kind of inheritance between the type classes, denoted by arrows. Looking in the left corner at the top, you will see the typeclass <span style=\"font-family: courier new,courier;\">Eq.<\/span> Now I&#8217;m curious how the definition of <span style=\"font-family: courier new,courier;\">Eq<\/span> will look like.&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">Eq<\/span> a where\r\n  (==) :: a -&gt; a -&gt; Bool\r\n  (\/=) :: a -&gt; a -&gt; Bool\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\nconcept <span style=\"color: #2b91af;\">bool<\/span> Equal(){\r\n  <span style=\"color: #0000ff;\">return<\/span> requires(T a, T b) {\r\n    { a == b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n    { a != b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n  };\r\n}<br \/><br \/>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span id=\"transmark\"><\/span>Let&#8217;s have a closer look at Haskell&#8217;s typeclass <span style=\"font-family: courier new,courier;\">Eq.<\/span><span style=\"font-family: courier new,courier;\"> Eq <\/span>requires, from its instances, that<span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<ul>\n<li>they have equal <span style=\"font-family: courier new,courier;\">==<\/span> and inequal <span style=\"font-family: courier new,courier;\">\/=<\/span> operation that returns a <span style=\"font-family: courier new,courier;\">Bool.<\/span><\/li>\n<li>both take two arguments (<span style=\"font-family: courier new,courier;\">a -&gt; a<\/span>) of the same type.<\/li>\n<\/ul>\n<p>Of course, the instances are the concrete types such as <span style=\"font-family: courier new,courier;\">Int<\/span>.<\/p>\n<p>Now, I have two questions in mind if I look at Haskell&#8217;s type hierarchy. What is the definition of the typeclass <span style=\"font-family: courier new,courier;\">Ord<\/span> in Haskell, and can we model the inheritance relation in C++?<\/p>\n<p>What is the definition of the typeclass <span style=\"font-family: courier new,courier;\">Ord<\/span> in Haskell?<\/p>\n<h3>Ord<\/h3>\n<p>&nbsp;<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #2b91af;\">Eq<\/span> a =&gt; Ord a where\r\n  compare :: a -&gt; a -&gt; Ordering\r\n  (&lt;) :: a -&gt; a -&gt; Bool\r\n  (&lt;=) :: a -&gt; a -&gt; Bool\r\n  (&gt;) :: a -&gt; a -&gt; Bool\r\n  (&gt;=) :: a -&gt; a -&gt; Bool\r\n  max :: a -&gt; a -&gt; a\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The most exciting point about the typeclass <span style=\"font-family: courier new,courier;\">Ord<\/span> is the first line of its definition. An instance of the typeclass <span style=\"font-family: courier new,courier;\">Ord<\/span> must already be an instance of the typeclass <span style=\"font-family: courier new,courier;\">Eq<\/span>. <span style=\"font-family: courier new,courier;\">Ordering<\/span> is an enumeration having the values <span style=\"font-family: courier new,courier;\">EQ,<\/span> <span style=\"font-family: courier new,courier;\">LT,<\/span> and <span style=\"font-family: courier new,courier;\">GT.<\/span><\/p>\n<p>How can we model the concept Ord in C++?<\/p>\n<h3><span style=\"font-family: courier new,courier;\">Eq -&gt; Ord<\/span><\/h3>\n<p>Of course, we can define the concept <span style=\"font-family: courier new,courier;\">Ord<\/span> by using all requirements of <span style=\"font-family: courier new,courier;\">Eq<\/span> and <span style=\"font-family: courier new,courier;\">Ord.&nbsp;<\/span>But we can do better in C++:<\/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%;\"> 0\r\n 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\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n47\r\n48\r\n49<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ conceptsDefintionOrd.cpp<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;unordered_set&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span>&lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\nconcept <span style=\"color: #2b91af;\">bool<\/span> Equal(){\r\n  <span style=\"color: #0000ff;\">return<\/span> requires(T a, T b){\r\n    { a == b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n    { a != b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n  };\r\n}\r\n\r\n<span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\nconcept <span style=\"color: #2b91af;\">bool<\/span> Ord(){\r\n  <span style=\"color: #0000ff;\">return<\/span> requires(T a, T b){\r\n    requires Equal&lt;T&gt;();\r\n    { a &lt;= b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n    { a &lt; b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n    { a &gt; b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n    { a &gt;= b } -&gt; <span style=\"color: #2b91af;\">bool<\/span>;\r\n  };\r\n}\r\n\r\n<span style=\"color: #2b91af;\">bool<\/span> areEqual(Equal a, Equal b){\r\n  <span style=\"color: #0000ff;\">return<\/span> a == b;\r\n}\r\n\r\nOrd getSmaller(Ord a, Ord b){\r\n  <span style=\"color: #0000ff;\">return<\/span> (a &lt; b) ? a : b;\r\n}\r\n    \r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n  \r\n  std::cout &lt;&lt; std::boolalpha &lt;&lt; std::endl;\r\n  \r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"areEqual(1, 5): \"<\/span> &lt;&lt; areEqual(1, 5) &lt;&lt; std::endl;\r\n  \r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"getSmaller(1, 5): \"<\/span> &lt;&lt; getSmaller(1, 5) &lt;&lt; std::endl;\r\n  \r\n  std::unordered_set&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; firSet{1, 2, 3, 4, 5};\r\n  std::unordered_set&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; secSet{5, 4, 3, 2, 1};\r\n  \r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"areEqual(firSet, secSet): \"<\/span> &lt;&lt; areEqual(firSet, secSet) &lt;&lt; std::endl;\r\n  \r\n  <span style=\"color: #008000;\">\/\/ auto smallerSet= getSmaller(firSet, secSet);<\/span>\r\n  \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>To simplify my job, I ignored the requirements <span style=\"font-family: courier new,courier;\">compare<\/span> and <span style=\"font-family: courier new,courier;\">max<\/span> in the concept <span style=\"font-family: courier new,courier;\">Ord. <\/span>The critical point about the concept is the line<span style=\"font-family: courier new,courier;\"> requires Equal&lt;T&gt;(). <\/span>Here I require that the type parameter<span style=\"font-family: courier new,courier;\"> <span style=\"font-family: courier new,courier;\">T<\/span> <\/span>fulfill the requirement <span style=\"font-family: courier new,courier;\">Equal. <\/span>If I use more requirements, such as in the definition of the concept <span style=\"font-family: courier new,courier;\">Equal,<\/span> each requirement from top to bottom will be checked. That will be done in a short-circuiting evaluation. So the first requirement returning <span style=\"font-family: courier new,courier;\">false<\/span> will end the process. <span style=\"font-family: courier new,courier;\"><br \/><\/span><\/p>\n<p>Equality and inequality are defined for the data types <span style=\"font-family: courier new,courier;\">int<\/span> and <span style=\"font-family: courier new,courier;\">std::unordered_set<\/span>. Therefore, the output should not surprise you.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5221\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionOrd.png\" alt=\"conceptsDefinitionOrd\" style=\"margin: 15px;\" width=\"519\" height=\"173\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionOrd.png 519w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionOrd-300x100.png 300w\" sizes=\"auto, (max-width: 519px) 100vw, 519px\" \/><\/p>\n<p>&nbsp;That will change dramatically if I use line 44 because the smaller\/bigger operators are not defined for <span style=\"font-family: courier new,courier;\">std::unordered_set.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5222\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionOrdError.png\" alt=\"conceptsDefinitionOrdError\" width=\"700\" height=\"264\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionOrdError.png 958w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionOrdError-300x113.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/conceptsDefinitionOrdError-768x289.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>I wrote a few articles for the German <a href=\"http:\/\/www.linux-magazin.de\/\">Linux-Magazin<\/a> and <a href=\"https:\/\/www.heise.de\/ix\/\">iX <\/a>about C++17. One of my blog readers asked me if they are available in English. I answered no. But I promised him to write about C++17 in my <a href=\"https:\/\/www.modernescpp.com\/index.php\/cpp17-core\">next post<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wrote a few posts about using concepts. Concepts are a named set of requirements. Let&#8217;s define a few concepts in this post.<\/p>\n","protected":false},"author":21,"featured_media":5219,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[415],"class_list":["post-5223","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-concepts"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5223","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=5223"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5223\/revisions"}],"predecessor-version":[{"id":6877,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5223\/revisions\/6877"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5219"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}