{"id":5510,"date":"2018-09-11T20:25:35","date_gmt":"2018-09-11T20:25:35","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-type-erasure-with-templates\/"},"modified":"2023-06-26T11:45:05","modified_gmt":"2023-06-26T11:45:05","slug":"c-core-guidelines-type-erasure-with-templates","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-type-erasure-with-templates\/","title":{"rendered":"C++ Core Guidelines: Type Erasure with Templates"},"content":{"rendered":"<p>In the last post <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-type-erasure\">C++ Core Guidelines: Type Erasure<\/a>, I presented two ways to implement type erasure: void pointers and object orientation. In this post, I bridge dynamic polymorphism (object orientation) with static polymorphism (templates) to get type erasure with templates.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5503\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/bridge.jpg\" alt=\"\" width=\"500\" height=\"333\" style=\"display: block; margin-left: auto; margin-right: auto;\" data-alt=\"bridge\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/bridge.jpg 1280w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/bridge-300x200.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/bridge-1024x682.jpg 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/bridge-768x512.jpg 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>As our starting point and reminder, here is type erasure based on object orientation.<\/p>\n<h2>Type erasure with object-orientation<\/h2>\n<p>Type erasure with object-orientation boils down to an inheritance hierarchy.<\/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;\">\/\/ typeErasureOO.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> BaseClass{                                     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n\t<span style=\"color: #006699; font-weight: bold;\">virtual<\/span> std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Bar<span style=\"color: #555555;\">:<\/span> BaseClass{\r\n\tstd<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n\t    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Bar\"<\/span>;\r\n\t}\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Foo<span style=\"color: #555555;\">:<\/span> BaseClass{\r\n\tstd<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override{\r\n\t    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Foo\"<\/span>;\r\n\t}\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">printName<\/span>(std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> BaseClass<span style=\"color: #555555;\">*&gt;<\/span> vec){    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> vec) std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v<span style=\"color: #555555;\">-&gt;<\/span>getName() <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\t\r\n\tstd<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\t\r\n\tFoo foo;\r\n\tBar bar; \r\n\t\r\n\tstd<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> BaseClass<span style=\"color: #555555;\">*&gt;<\/span> vec{<span style=\"color: #555555;\">&amp;<\/span>foo, <span style=\"color: #555555;\">&amp;<\/span>bar};    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n\t\r\n\tprintName(vec);\r\n\t\r\n\tstd<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 key point is that you can use instances of <code>Foo<\/code> or <code>Bar<\/code> instead of an instance for <code>BaseClass.<\/code> For further details, read the post <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-type-erasure\">C++ Core Guidelines: Type Erasure.<\/a><\/p>\n<p>What are the pros and cons of this implementation with OO?<\/p>\n<p><strong>Pros:<\/strong><\/p>\n<ul>\n<li>Typesafe<\/li>\n<li>Easy to implement<\/li>\n<\/ul>\n<p><strong>Cons:<\/strong><\/p>\n<ul>\n<li>Virtual dispatch<\/li>\n<li>Intrusive because the derived class must know about its base<\/li>\n<\/ul>\n<p>Let&#8217;s see which drawbacks type erasure with templates solves.<\/p>\n<\/p>\n<h2>Type erasure with templates<\/h2>\n<p>Here is the templates program, which corresponds to the previous OO program.<\/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;\">\/\/ typeErasure.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;memory&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Object<\/span> {                                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n\t \r\n<span style=\"color: #9999ff;\">public:<\/span>\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> T<span style=\"color: #555555;\">&gt;<\/span>                                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n    Object(<span style=\"color: #006699; font-weight: bold;\"><\/span>T<span style=\"color: #555555;\">&amp;&amp;<\/span> obj)<span style=\"color: #555555;\">:<\/span> object(std<span style=\"color: #555555;\">::<\/span>make_shared<span style=\"color: #555555;\">&lt;<\/span>Model<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;&gt;<\/span>(std<span style=\"color: #555555;\">::forward&lt;T&gt;<\/span>(obj))){}\r\n      \r\n    std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> object<span style=\"color: #555555;\">-&gt;<\/span>getName(); \r\n    }\r\n\t\r\n   <span style=\"color: #006699; font-weight: bold;\">struct<\/span> Concept {                                         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\r\n       <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #555555;\">~<\/span>Concept() {}\r\n\t   <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n   };\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> T <span style=\"color: #555555;\">&gt;<\/span>                                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (6)<\/span>\r\n   <span style=\"color: #006699; font-weight: bold;\">struct<\/span> Model <span style=\"color: #555555;\">:<\/span> Concept {\r\n       Model(<span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">&amp;<\/span> t) <span style=\"color: #555555;\">:<\/span> object(t) {}\r\n\t   std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n\t\t   <span style=\"color: #006699; font-weight: bold;\">return<\/span> object.getName();\r\n\t   }\r\n     <span style=\"color: #9999ff;\">private:<\/span>\r\n       T object;\r\n   };\r\n\r\n   std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> Concept<span style=\"color: #555555;\">&gt;<\/span> object;\r\n};\r\n\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">printName<\/span>(std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>Object<span style=\"color: #555555;\">&gt;<\/span> vec){                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (7)<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> vec) std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v.getName() <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Bar{\r\n    std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (8)<\/span>\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Bar\"<\/span>;\r\n    }\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Foo{\r\n    std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (8)<\/span>\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Foo\"<\/span>;\r\n    }\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\t\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\t\r\n    std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>Object<span style=\"color: #555555;\">&gt;<\/span> vec{Object(Foo()), Object(Bar())};  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n\t\r\n    printName(vec);\r\n\t\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>Okay, what is happening here? Don&#8217;t be irritated by the names <code>Object<\/code>, <code>Concept<\/code>, and <code>Model<\/code>. They are typically used for type erasure in the literature. So I stick to them.<\/p>\n<p>First of all. My <code>std:<\/code>:vector uses instances (1) of type <code>Object<\/code> (2) and not pointers, such as in the first OO example. These instances can be created with arbitrary types because it has a generic constructor (3). <span style=\"font-family: courier new, courier;\">Object<\/span> has the <code>getName<\/code> method (4), which is directly forwarded to the <code>getName<\/code> of object. object is of type <code>std::shared_ptr&lt;const Concept&gt;<\/code>. The <code>getName<\/code> method of <code>Concept<\/code> is pure virtual (5). Therefore, due to virtual dispatch, the <code>getName<\/code> method of <code>Model<\/code> (6) is used.&nbsp; In the end, the <code>getName<\/code> methods of <code>Bar<\/code> and <code>Foo<\/code> (8) are applied in the <code>printName <\/code>function (7).<\/p>\n<p>Here is the output of the program.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5504\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/typeErasure.png\" alt=\"typeErasure\" width=\"300\" height=\"178\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/typeErasure.png 612w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/typeErasure-300x178.png 300w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Of course, this implementation is type-safe.<\/p>\n<h2>Error messages<\/h2>\n<p>I&#8217;m currently giving a C++ class. We quite often have discussions about error messages with templates; therefore, I was curious about the error messages if I change the classes <code>Foo<\/code> and <code>Bar<\/code> a little bit. Here is the incorrect implementation:<\/p>\n<p>&nbsp;<\/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;\">struct<\/span> Bar{\r\n    std<span style=\"color: #555555;\">::<\/span>string get() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {                             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Bar\"<\/span>;\r\n    }\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Foo{\r\n    std<span style=\"color: #555555;\">::<\/span>string get_name() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {                        <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Foo\"<\/span>;\r\n    }\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I renamed the method <code>getName<\/code> to <code>get<\/code> (1) and to <code>get_name (2).&nbsp;<\/code><\/p>\n<p>Here are the error messages copied from the <a href=\"https:\/\/godbolt.org\/\">Compiler Explorer. <\/a><\/p>\n<p>I start with the ugliest one from Clang 6.0.0 and end with the quite good one from&nbsp; GCC 8.2.&nbsp; The error message from MSVC 19 is something in between. I was astonished because I thought clang would produce the clearest error message.<\/p>\n<h3>Clang 6.0.0<\/h3>\n<p>I can only display half of the error message because it&#8217;s too much for one screenshot.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5505\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClang.png\" alt=\"errorClang\" width=\"700\" height=\"426\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClang.png 1071w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClang-300x183.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClang-1024x623.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClang-768x468.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h3>MSVC 19<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5506\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorWindows.png\" alt=\"errorWindows\" width=\"700\" height=\"215\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorWindows.png 1451w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorWindows-300x92.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorWindows-1024x315.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorWindows-768x236.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<h3>GCC 8.2<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5507\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorGcc.png\" alt=\"errorGcc\" width=\"700\" height=\"124\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorGcc.png 1289w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorGcc-300x53.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorGcc-1024x182.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorGcc-768x136.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Please look carefully at the screenshot of GCC 8.2. It says: &#8220;<samp>27:20: error: &#8216;const struct Foo&#8217; has no member named &#8216;getName&#8217;; did you mean &#8216;get_name&#8217;?&#8221;. <\/samp>Isn&#8217;t that great?<\/p>\n<p>The error message from MSVC, particularly from Clang, is quite bad.&nbsp; This should not be the end of my post.<\/p>\n<h2>My Challenge<\/h2>\n<p>Now I want to solve the challenge: How can I detect if a given class has a specific method at compile time? In our case, the classes <code>Bar<\/code> and <code>Foo<\/code> should have a method <code>getName. <\/code>I played with <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/sfinae\">SFINAE<\/a>, experimented with the C++11 variant <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/enable_if\">std::enable_if<\/a>, and ended with the <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/experimental\/is_detected\">detection idiom<\/a>, part of the <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html\">library fundamental TS v2<\/a>. You must include the header from the experimental namespace (1) to use it. Here is the modified example:<\/p>\n<p>&nbsp;<\/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;\">\/\/ typeErasureDetection.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;experimental\/type_traits&gt;                                 <\/span><span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)          <\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;memory&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/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> T<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">using<\/span> getName_t <span style=\"color: #555555;\">=<\/span> decltype( std<span style=\"color: #555555;\">::<\/span>declval<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&amp;&gt;<\/span>().getName() );         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Object<\/span> {                                              \r\n\t \r\n<span style=\"color: #9999ff;\">public:<\/span>\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> T<span style=\"color: #555555;\">&gt;<\/span>                                   \r\n    Object(<span style=\"color: #006699; font-weight: bold;\"><\/span>T<span style=\"color: #555555;\">&amp;&amp;<\/span> obj)<span style=\"color: #555555;\">:<\/span> object(std<span style=\"color: #555555;\">::<\/span>make_shared<span style=\"color: #555555;\">&lt;<\/span>Model<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;&gt;<\/span>(std<span style=\"color: #555555;\">::forward&lt;T&gt;<\/span>(obj))){   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n      \r\n        static_assert(std<span style=\"color: #555555;\">::<\/span>experimental<span style=\"color: #555555;\">::<\/span>is_detected<span style=\"color: #555555;\">&lt;<\/span>getName_t, decltype(obj)<span style=\"color: #555555;\">&gt;::<\/span>value, \r\n                                                     <span style=\"color: #cc3300;\">\"No method getName available!\"<\/span>);\r\n        \r\n    }\r\n      \r\n    std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {                           \r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> object<span style=\"color: #555555;\">-&gt;<\/span>getName(); \r\n    }\r\n\t\r\n   <span style=\"color: #006699; font-weight: bold;\">struct<\/span> Concept {                                         \r\n       <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #555555;\">~<\/span>Concept() {}\r\n\t   <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n   };\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> T <span style=\"color: #555555;\">&gt;<\/span>                                   \r\n   <span style=\"color: #006699; font-weight: bold;\">struct<\/span> Model <span style=\"color: #555555;\">:<\/span> Concept {\r\n       Model(<span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">&amp;<\/span> t) <span style=\"color: #555555;\">:<\/span> object(t) {}\r\n\t   std<span style=\"color: #555555;\">::<\/span>string getName() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n\t\t   <span style=\"color: #006699; font-weight: bold;\">return<\/span> object.getName();\r\n\t   }\r\n     <span style=\"color: #9999ff;\">private:<\/span>\r\n       T object;\r\n   };\r\n\r\n   std<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> Concept<span style=\"color: #555555;\">&gt;<\/span> object;\r\n};\r\n\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">printName<\/span>(std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>Object<span style=\"color: #555555;\">&gt;<\/span> vec){                    \r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> vec) std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v.getName() <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Bar{\r\n    std<span style=\"color: #555555;\">::<\/span>string get() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {                           \r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Bar\"<\/span>;\r\n    }\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Foo{\r\n    std<span style=\"color: #555555;\">::<\/span>string get_name() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {                           \r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Foo\"<\/span>;\r\n    }\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\t\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\t\r\n    std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>Object<span style=\"color: #555555;\">&gt;<\/span> vec{Object(Foo()), Object(Bar())};  <span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n\t\r\n    printName(vec);\r\n\t\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>I added lines (1), (2), and (3). Line (2) deduces the member function type. <span style=\"font-family: courier new, courier;\">std::declval<\/span> from C++11 is a function that allows you to use member functions in expressions without needing to construct the object. The crucial part of the detection idiom is the function<code> std::experimental::is_detected<\/code> from the type traits library in the <code>static_assert<\/code> (3).<\/p>\n<p>Let&#8217;s see what Clang 6.0.0 produces if I execute the program in the Compiler Explorer:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5508\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetection.png\" alt=\"errorClangDetection\" width=\"700\" height=\"509\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetection.png 1214w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetection-300x218.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetection-1024x744.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetection-768x558.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Wow! That is still too much output. To be honest. The state of the feature is still experimental. If you look carefully at the output of the error message and you search for&nbsp; <code>static_assert,<\/code> , you find the answer you are looking for.&nbsp; Here are the first three lines of the output.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5509\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetectionFocus.png\" alt=\"errorClangDetectionFocus\" width=\"700\" height=\"60\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetectionFocus.png 1089w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetectionFocus-300x26.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetectionFocus-1024x88.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/09\/errorClangDetectionFocus-768x66.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Great! At least you can grep for the string.&#8221;<code>No method getName available<\/code>&#8221; in the error message.<\/p>\n<p>Before I end the post, here are the pros and cons of type erasure with templates:<\/p>\n<p><strong>Pros:<\/strong><\/p>\n<ul>\n<li>Typesafe<\/li>\n<li>Non-intrusive because the derived class doesn&#8217;t need to know the base class<\/li>\n<\/ul>\n<p><strong>Cons:<\/strong><\/p>\n<ul>\n<li>Virtual dispatch<\/li>\n<li>Difficult to implement<\/li>\n<\/ul>\n<p>In the end, the difference between type erasure with object orientation and with templates mainly boils down to two points:<\/p>\n<ul>\n<li>Intrusive versus non-intrusive<\/li>\n<li>Easy versus challenging to implement<\/li>\n<\/ul>\n<h2>What&#8217;s next?<\/h2>\n<p>This is the end of my detour. in the <a href=\"https:\/\/goo.gl\/FGZ8fT\">next post<\/a>, I will continue my journey through generic programming; to be more specific, I will write about concepts.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last post C++ Core Guidelines: Type Erasure, I presented two ways to implement type erasure: void pointers and object orientation. In this post, I bridge dynamic polymorphism (object orientation) with static polymorphism (templates) to get type erasure with templates.<\/p>\n","protected":false},"author":21,"featured_media":5503,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[420],"class_list":["post-5510","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-type-erasure"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5510","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=5510"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5510\/revisions"}],"predecessor-version":[{"id":6813,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5510\/revisions\/6813"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5503"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5510"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5510"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5510"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}