{"id":3141,"date":"2018-09-06T20:20:03","date_gmt":"2018-09-06T18:20:03","guid":{"rendered":"https:\/\/mariusbancila.ro\/blog\/?p=3141"},"modified":"2021-11-16T08:47:54","modified_gmt":"2021-11-16T06:47:54","slug":"when-a-type-is-not-a-type","status":"publish","type":"post","link":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/","title":{"rendered":"When a type is not a type"},"content":{"rendered":"\n<figure class=\"wp-block-pullquote\"><blockquote><p>This article has been updated for C++20.<\/p><\/blockquote><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s take a look at the following code sample:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">template &lt;typename T> \nstruct foo\n{\n   foo(T) {}\n};\n\nint main()\n{\n   std::pair   p{ 1, \"one\" };\n   std::vector v{ 1, 2 };\n   foo         f{ 42 };\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Here, <tt>p<\/tt> is a <tt>std::pair<\/tt>, <tt>v<\/tt> is a <tt>std::vector<\/tt>, and <tt>f<\/tt> is a <tt>foo<\/tt>. But there is no such thing as a <tt>std::vector<\/tt> type (nor <tt>std::pair<\/tt> or <tt>foo<\/tt>). <tt>std::vector&lt;int&gt;<\/tt> is a type, and <tt>std::vector&lt;T&gt;<\/tt> is a type template, but <tt>std::vector<\/tt> is just a placeholder that activates a C++17 feature called <em>class template argument deduction<\/em> (which we will call CTAD for short).<\/p>\n\n\n\n<!--more-->\n\n\n\n<h3 class=\"wp-block-heading\">Why CTAD?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Prior to C++17, you had to explicitly specify all the class template arguments, as all of them must be known in order to instantiate the class template. Therefore, the code above would have looked like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">std::pair&lt;int, char const*> p{ 1, \"one\" };\nstd::vector&lt;int>            v{ 1, 2 };\nfoo&lt;int>                    f{ 42 };<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Since function template argument deduction was available for a long time, the workaround in C++11 was to provide a <tt>make_xxx()<\/tt> function that creates instance of the class template, and use <tt>auto<\/tt> as placeholder for the type.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">auto p = std::make_pair(1, \"one\");<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Of course, not all the standard types have such a helper function, so it was often the case that users wrote their own make functions. Here you can see an example of a <tt>make_vector()<\/tt> variadic function template that creates a vector:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">template &lt;class T, class... Ts, class Allocator = std::allocator&lt;T>>\nauto make_vector(T&amp;&amp; first, Ts&amp;&amp;... args)\n{\n   return std::vector&lt;std::decay_t&lt;T>, Allocator>{ \n      std::forward&lt;T>(first), \n      std::forward&lt;Ts>(args)... };\n}\n\nauto v = make_vector(1, 2);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Here is another example for the user-defined class <tt>foo<\/tt>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">template &lt;typename T>\nconstexpr foo&lt;T> make_foo(T&amp;&amp; value)\n{\n   return foo{ value };\n}\n\nauto f = make_foo(42);<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">How it works<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When the compiler encounters a declaration of a variable, or a function-style cast using the name of a class template, it builds a set of deduction guides, which is basically fictional functions template representing constructor signatures of a hypothetical class type. These implicit deduction guides created by the compiler can be complemented with user-defined deduction guides. They are then used for performing template argument deduction and overload resolution for initializing objects of this hypothetical class.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here are several examples (not the complete list) for the implicit deduction types that the compiler constructs for the <tt>std::pair<\/tt> class template:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">template &lt;class T1, class T2>\nstd::pair&lt;T1, T2> F();\n\ntemplate &lt;class T1, class T2>\nstd::pair&lt;T1, T2> F(T1 const&amp; x, T2 const&amp; y);\n\ntemplate &lt;class T1, class T2, class U1, class U2>\nstd::pair&lt;T1, T2> F(U1&amp;&amp; x, U2&amp;&amp; y);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The implicit deduction guides are generated from the constructors of the class template (the default constructor, the copy constructor, and all the other constructor with the type arguments copied in their exact order). If the class template does not have any constructor, a deduction guide is created for a hypothetical default constructor. In any case, a deduction guide for a hypothetical copy constructor is created.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">User-defined deduction guides are very similar to function signature with trailing return type but without the <tt>auto<\/tt> keyword (after all, they represent fictional constructor signatures). They must be defined in the scope of the class template they apply to. So an example for <tt>std::pair<\/tt> could be (although this is actually provided implicitly by the compiler):<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">namespace std {\n   template &lt;class T1, class T2>\n   pair(T1&amp;&amp; v1, T2&amp;&amp; v2)->pair&lt;T1, T2>;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Consider the following class type <tt>bar<\/tt> that has a constructor using iterators:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">template &lt;typename T>\nstruct bar\n{\n   template &lt;class Iter>\n   bar(Iter first, Iter last) {}\n};<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The idea is to be able to initialize objects of this type template as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">int arr[] = { 1,2,3,4,5 };\nbar b{std::begin(arr), std::end(arr)};<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">However, this does not work. For instance, the VC++ compiler generates the following errors:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">error C2672: 'bar': no matching overloaded function found\nerror C2783: 'bar&lt;T> bar(Iter,Iter)': could not deduce template argument for 'T'<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These can be fixed using a user-defined deduction guide as shown below:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">template &lt;class Iter>\nbar(Iter first, Iter last)->bar&lt;typename std::iterator_traits&lt;Iter>::value_type>;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The deduction guides don&#8217;t have to be templates. Considering the class <tt>foo<\/tt> from above, we can have the following deduction guide that forces the compiler to always create instances of <tt>foo&lt;std::string&gt;<\/tt> when a <tt>char const*<\/tt> is used as argument.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">foo(char const *)->foo&lt;std::string>;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This example can be further applied on the <tt>std::pair<\/tt> class template, so that <tt>std::string<\/tt> is always used instead of <tt>char const*<\/tt>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">namespace std {\n   template &lt;class T>\n   pair(T&amp;&amp;, char const *)->pair&lt;T, std::string>;\n\n   template &lt;class T>\n   pair(char const *, T&amp;&amp;)->pair&lt;std::string, T>;\n\n   pair(char const *, char const *)->pair&lt;std::string, std::string>;\n}\n\nstd::pair  p1{ 1, \"one\" };    \/\/ std::pair&lt;int, std::string>\nstd::pair  p2{ \"one\", 1 };    \/\/ std::pair&lt;std::string, int>\nstd::pair  p3{ \"1\", \"one\" };  \/\/ std::pair&lt;std::string, std::string><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Gotchas<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CTAD does not take place when the template argument list is present. The following two declarations are both legal:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">std::pair&lt;int, std::string> p1 {1, \"one\"};\nstd::pair                   p2 {1, \"one\"};<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">However, none of the following is valid, as CTAD does not take place:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">std::pair&lt;>    p1 { 1, \"one\" };\nstd::pair&lt;int> p2 { 1, \"one\" };<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you have aggregate types that you want to initialize taking advantage of CTAD then you probably need to define your own deduction guides. Let&#8217;s consider the following class template <tt>foo<\/tt>. Initializing objects without providing the template argument list does not work.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">template &lt;typename T> \nstruct foo\n{\n   T t;\n};\n\nfoo f{ 42 };  \/\/ error: no matching overloaded function found<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To leverage CTAD you need to define your own deduction guide, which in this case is as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">template &lt;typename T>\nfoo(T)->foo&lt;T>;<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">C++20 support for aggregate types<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The C++20 standard has added support for aggregate types. Defining a deduction rule as mentioned above is no longer needed for aggregates, provided that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>the variable is initialized from a non-empty list of variables<\/li><li>any dependent base class has no virtual functions or virtual base classes<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Therefore, in C++20 the previous example with the foo&lt;T> class template no longer requires your own deduction guide.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Class template argument deduction is a useful feature in C++17 that helps developers to simplify the code by avoiding writing the template argument list when initializing objects of class templates (or when performing function-style casts). The compiler provides an implicit set of deduction guides, which are fictional function templates for a hypothetical class and uses them to perform template argument deduction and overload resolution. However, you can extend this set of deduction guides with your own, and in some cases, such as for aggregate types, you need to do so.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">See also<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can learn more about this feature from the following articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/class_template_argument_deduction\" target=\"_blank\" rel=\"noopener\">Class template argument deduction<\/a><\/li><li><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/template_argument_deduction\" target=\"_blank\" rel=\"noopener\">Template argument deduction<\/a><\/li><li><a href=\"https:\/\/arne-mertz.de\/2017\/06\/class-template-argument-deduction\/\" target=\"_blank\" rel=\"noopener\">Modern C++ Features \u2013 Class Template Argument Deduction<\/a><\/li><li><a href=\"https:\/\/blog.tartanllama.xyz\/deduction-for-class-templates\/\" target=\"_blank\" rel=\"noopener\">Template argument deduction for class template constructors<\/a><\/li><li><a href=\"https:\/\/medium.com\/@barryrevzin\/quirks-in-class-template-argument-deduction-ad08af42ebd6\" target=\"_blank\" rel=\"noopener\">Quirks in Class Template Argument Deduction<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Class template argument deduction is a useful feature in C++17 that helps developers to simplify the code by avoiding writing the template argument list when initializing objects of class templates (or when performing function-style casts). The compiler provides an implicit set of deduction guides, which are fictional function templates for a hypothetical class and uses them to perform template argument deduction and overload resolution. However, you can extend this set of deduction guides with your own, and in some cases, such as for aggregate types, you need to do so.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[7],"tags":[451,564,323],"class_list":["post-3141","post","type-post","status-publish","format-standard","hentry","category-c","tag-c","tag-metaprogramming","tag-templates"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Marius Bancila\"\/>\n\t<meta name=\"keywords\" content=\"c++,metaprogramming,templates\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Marius Bancila&#039;s Blog | About code. Mostly on C++\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"When a type is not a type\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2018-09-06T18:20:03+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2021-11-16T06:47:54+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"When a type is not a type\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#article\",\"name\":\"When a type is not a type\",\"headline\":\"When a type is not a type\",\"author\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\"},\"datePublished\":\"2018-09-06T20:20:03+02:00\",\"dateModified\":\"2021-11-16T08:47:54+02:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#webpage\"},\"articleSection\":\"C++, C++, metaprogramming, templates\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"name\":\"IT\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"position\":2,\"name\":\"IT\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"name\":\"Software\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"position\":3,\"name\":\"Software\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"name\":\"C++\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"name\":\"IT\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"position\":4,\"name\":\"C++\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#listItem\",\"name\":\"When a type is not a type\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"name\":\"Software\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#listItem\",\"position\":5,\"name\":\"When a type is not a type\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"name\":\"C++\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\",\"name\":\"Marius Bancila's Blog\",\"description\":\"About code. Mostly on C++\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/\",\"name\":\"Marius Bancila\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a84dd2831d955c38355ddea55df4df260809b88f36408bc14fd4eab8f7f131c9?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Marius Bancila\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#webpage\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/\",\"name\":\"When a type is not a type\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2018\\\/09\\\/06\\\/when-a-type-is-not-a-type\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"datePublished\":\"2018-09-06T20:20:03+02:00\",\"dateModified\":\"2021-11-16T08:47:54+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\",\"name\":\"Marius Bancila's Blog\",\"description\":\"About code. Mostly on C++\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"When a type is not a type","description":"","canonical_url":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/","robots":"max-image-preview:large","keywords":"c++,metaprogramming,templates","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#article","name":"When a type is not a type","headline":"When a type is not a type","author":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"publisher":{"@id":"https:\/\/mariusbancila.ro\/blog\/#organization"},"datePublished":"2018-09-06T20:20:03+02:00","dateModified":"2021-11-16T08:47:54+02:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#webpage"},"isPartOf":{"@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#webpage"},"articleSection":"C++, C++, metaprogramming, templates"},{"@type":"BreadcrumbList","@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/#listItem","position":1,"name":"Home","item":"https:\/\/mariusbancila.ro\/blog\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","name":"IT"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","position":2,"name":"IT","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","name":"Software"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","position":3,"name":"Software","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","name":"C++"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","name":"IT"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","position":4,"name":"C++","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#listItem","name":"When a type is not a type"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","name":"Software"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#listItem","position":5,"name":"When a type is not a type","previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","name":"C++"}}]},{"@type":"Organization","@id":"https:\/\/mariusbancila.ro\/blog\/#organization","name":"Marius Bancila's Blog","description":"About code. Mostly on C++","url":"https:\/\/mariusbancila.ro\/blog\/"},{"@type":"Person","@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author","url":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/","name":"Marius Bancila","image":{"@type":"ImageObject","@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/a84dd2831d955c38355ddea55df4df260809b88f36408bc14fd4eab8f7f131c9?s=96&d=mm&r=g","width":96,"height":96,"caption":"Marius Bancila"}},{"@type":"WebPage","@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#webpage","url":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/","name":"When a type is not a type","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/mariusbancila.ro\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/#breadcrumblist"},"author":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"creator":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"datePublished":"2018-09-06T20:20:03+02:00","dateModified":"2021-11-16T08:47:54+02:00"},{"@type":"WebSite","@id":"https:\/\/mariusbancila.ro\/blog\/#website","url":"https:\/\/mariusbancila.ro\/blog\/","name":"Marius Bancila's Blog","description":"About code. Mostly on C++","inLanguage":"en-US","publisher":{"@id":"https:\/\/mariusbancila.ro\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Marius Bancila's Blog | About code. Mostly on C++","og:type":"article","og:title":"When a type is not a type","og:url":"https:\/\/mariusbancila.ro\/blog\/2018\/09\/06\/when-a-type-is-not-a-type\/","article:published_time":"2018-09-06T18:20:03+00:00","article:modified_time":"2021-11-16T06:47:54+00:00","twitter:card":"summary","twitter:title":"When a type is not a type"},"aioseo_meta_data":{"post_id":"3141","title":null,"description":null,"keywords":[],"keyphrases":{"focus":[],"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":[],"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":{"id":"aioseo-article-6369777e52ecb","slug":"article","graphName":"Article","label":"Article","properties":{"type":"BlogPosting","name":"#post_title","headline":"#post_title","description":"#post_excerpt","image":"","keywords":"","author":{"name":"#author_name","url":"#author_url"},"dates":{"include":true,"datePublished":"","dateModified":""}}},"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":"{\"article\":{\"articleType\":\"BlogPosting\"},\"course\":{\"name\":\"\",\"description\":\"\",\"provider\":\"\"},\"faq\":{\"pages\":[]},\"product\":{\"reviews\":[]},\"recipe\":{\"ingredients\":[],\"instructions\":[],\"keywords\":[]},\"software\":{\"reviews\":[],\"operatingSystems\":[]},\"webPage\":{\"webPageType\":\"WebPage\"}}","pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":{"locations":{"business":{"name":"","businessType":"","image":"","areaServed":"","urls":{"website":"","aboutPage":"","contactPage":""},"address":{"streetLine1":"","streetLine2":"","zipCode":"","city":"","state":"","country":"","addressFormat":"#streetLineOne\n#streetLineTwo\n#city, #state #zipCode"},"contact":{"email":"","phone":"","phoneFormatted":"","fax":"","faxFormatted":""},"ids":{"vat":"","tax":"","chamberOfCommerce":""},"payment":{"priceRange":"","currenciesAccepted":"","methods":""}}},"openingHours":{"useDefaults":true,"show":true,"alwaysOpen":false,"use24hFormat":false,"timezone":"","labels":{"closed":"","alwaysOpen":""},"days":{"monday":{"open24h":false,"closed":false,"openTime":"09:00","closeTime":"17:00"},"tuesday":{"open24h":false,"closed":false,"openTime":"09:00","closeTime":"17:00"},"wednesday":{"open24h":false,"closed":false,"openTime":"09:00","closeTime":"17:00"},"thursday":{"open24h":false,"closed":false,"openTime":"09:00","closeTime":"17:00"},"friday":{"open24h":false,"closed":false,"openTime":"09:00","closeTime":"17:00"},"saturday":{"open24h":false,"closed":false,"openTime":"09:00","closeTime":"17:00"},"sunday":{"open24h":false,"closed":false,"openTime":"09:00","closeTime":"17:00"}}}},"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2021-03-18 21:04:15","updated":"2025-12-12 07:50:13","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"author_meta":{"display_name":"Marius Bancila","author_link":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/"},"featured_img":null,"jetpack_publicize_connections":[],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Marius Bancila","author_link":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/"},"uagb_comment_info":0,"uagb_excerpt":"Class template argument deduction is a useful feature in C++17 that helps developers to simplify the code by avoiding writing the template argument list when initializing objects of class templates (or when performing function-style casts). The compiler provides an implicit set of deduction guides, which are fictional function templates for a hypothetical class and uses&hellip;","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">C++<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">C++<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">C++<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">metaprogramming<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">templates<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">C++<\/span>","<span class=\"advgb-post-tax-term\">metaprogramming<\/span>","<span class=\"advgb-post-tax-term\">templates<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 8 years ago","modified":"Updated 5 years ago"},"absolute_dates":{"created":"Posted on September 6, 2018","modified":"Updated on November 16, 2021"},"absolute_dates_time":{"created":"Posted on September 6, 2018 8:20 pm","modified":"Updated on November 16, 2021 8:47 am"},"featured_img_caption":"","series_order":"","jetpack_shortlink":"https:\/\/wp.me\/pYNdv-OF","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3141","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/comments?post=3141"}],"version-history":[{"count":10,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3141\/revisions"}],"predecessor-version":[{"id":4342,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3141\/revisions\/4342"}],"wp:attachment":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/media?parent=3141"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/categories?post=3141"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/tags?post=3141"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}