{"id":10615,"date":"2016-11-16T13:00:45","date_gmt":"2016-11-16T20:00:45","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/?p=10615"},"modified":"2019-02-18T18:04:34","modified_gmt":"2019-02-18T18:04:34","slug":"sfinae-update","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/sfinae-update\/","title":{"rendered":"Updates to Expression SFINAE in VS 2017 RC"},"content":{"rendered":"<p>Throughout the VS 2015 cycle we&#8217;ve been focusing on the quality of our expression SFINAE implementation. Because expression SFINAE issues can be subtle and complex we&#8217;ve been using popular libraries such as <a href=\"http:\/\/www.boost.org\/\">Boost<\/a> and <a href=\"https:\/\/github.com\/microsoft\/Range-V3-VS2015\">Microsoft&#8217;s fork of Range-v3<\/a>\u00a0to validate our implementation and find remaining bugs. As we shift the compiler team&#8217;s focus to Visual Studio 2017 release we&#8217;re excited to tell you about the improvements we&#8217;ve made in correctly parsing expression SFINAE.<\/p>\n<p>We&#8217;ve been tracking the changes and improvements to our parsing of expression SFINAE throughout the Visual Studio 2015 and 2017 cycle. The improvements added to VS 2017 RC (since VS 2015 Update 3) are listed below. We&#8217;ve also updated <a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2016\/06\/07\/expression-sfinae-improvements-in-vs-2015-update-3\/\">the original blog post<\/a> with our recent improvements so you can track all of our progress in one place. <\/p>\n<h3>Improvements since Visual Studio 2015 Update 3<\/h3>\n<p>We now correctly compile code that constructs temporary objects as Range-v3 does extensively:<\/p>\n<pre class=\"prettyprint\">\n\t\t#include &lt;type_traits&gt;\n\t\t\n\t\ttemplate&lt;typename T, std::enable_if_t&lt;std::is_integral&lt;T&gt;{}&gt; * = nullptr&gt;\n\t\tchar f(T *);\n\t\t\n\t\ttemplate&lt;typename T&gt;\n\t\tshort f(...);\n\t\t\n\t\tint main()\n\t\t{\n\t\t\tstatic_assert(sizeof(f&lt;int&gt;(nullptr)) == sizeof(char), &quot;fail&quot;);\n\t\t\tstatic_assert(sizeof(f&lt;int *&gt;(nullptr)) == sizeof(short), &quot;fail&quot;);\n\t\t}\n<\/pre>\n<p>We&#8217;ve also improved access checks for SFINAE which are illustrated in this code sample:<\/p>\n<pre class=\"prettyprint\">\n\t\ttemplate &lt;typename T&gt; class S {\n\t\tprivate:\n\t\t\ttypedef T type;\n\t\t};\n\t\t\n\t\ttemplate &lt;typename T&gt; class S&lt;T *&gt; {\n\t\tpublic:\n\t\t\ttypedef T type;\n\t\t};\n\t\t\n\t\ttemplate &lt;typename T, typename S&lt;T&gt;::type * = nullptr&gt;\n\t\tchar f(T);\n\t\t\n\t\ttemplate&lt;typename T&gt;\n\t\tshort f(...);\n\t\t\n\t\tint main()\n\t\t{\n\t\t\tstatic_assert(sizeof(f&lt;int&gt;(0)) == 2, &quot;fail&quot;); \/\/ fails in VS2015\n\t\t\tstatic_assert(sizeof(f&lt;int *&gt;(nullptr)) == 1, &quot;fail&quot;);\n\t\t}\n<\/pre>\n<p>Lastly, we&#8217;ve improved support for <code>void_t<\/code> when used inside of a typename as found in Boost Hana:<\/p>\n<pre class=\"prettyprint\">\n\t\ttemplate&lt;typename T, typename U&gt;\n\t\tstruct std_common_type {};\n\t\t\n\t\ttemplate&lt;typename T&gt;\n\t\tstruct std_common_type&lt;T, T&gt; { using type = T; };\n\t\t\n\t\ttemplate&lt;typename T, typename U&gt;\n\t\tstruct is_same { static const bool value = false; };\n\t\t\n\t\ttemplate&lt;typename T&gt;\n\t\tstruct is_same&lt;T, T&gt; { static const bool value = true; };\n\t\t\n\t\ttemplate&lt;bool, typename T&gt;\n\t\tstruct enable_if {};\n\t\t\n\t\ttemplate&lt;typename T&gt;\n\t\tstruct enable_if&lt;true, T&gt; { using type = T; };\n\t\t\n\t\ttemplate&lt;typename...&gt; using void_t = void;\n\t\t\n\t\ttemplate &lt;typename T, typename U = T, typename = void&gt;\n\t\tstruct EqualityComparable1 { static const bool value = false; };\n\t\t\n\t\ttemplate &lt;typename T, typename U&gt;\n\t\tstruct EqualityComparable1&lt;T, U, typename enable_if&lt;!is_same&lt;T, U&gt;::value, void_t&lt;typename std_common_type&lt;T, U&gt;::type&gt;&gt;::type&gt;\n\t\t{\n\t\t\tstatic const bool value = true;\n\t\t};\n\t\t\n\t\ttemplate &lt;typename T, typename U = T, typename = void&gt;\n\t\tstruct EqualityComparable2 { static const bool value = false; };\n\t\t\n\t\ttemplate &lt;typename T, typename U&gt;\n\t\tstruct EqualityComparable2&lt;T, U, void_t&lt;typename std_common_type&lt;T, U&gt;::type&gt;&gt;\n\t\t{\n\t\t\tstatic const bool value = true;\n\t\t};\n\t\t\n\t\tvoid f()\n\t\t{\n\t\t\tstruct S1 {};\n\t\t\tstruct S2 {};\n\t\t\tstatic_assert(!EqualityComparable1&lt;S1, S2&gt;::value, &quot;fail&quot;); \/\/ fails in VS2015\n\t\t\tstatic_assert(!EqualityComparable2&lt;S1, S2&gt;::value, &quot;fail&quot;);\n\t\t}\n<\/pre>\n<h3>In closing<\/h3>\n<p>As always, we welcome your feedback. Please give us feedback about expression SFINAE in the comments below or through e-mail at <a href=\"mailto:visualcpp@microsoft.com\">visualcpp@microsoft.com<\/a>.<\/p>\n<p>If you encounter other problems with Visual C++ in VS 2017 RC please let us know via the Report a Problem option, either from the installer or the Visual Studio IDE itself. For suggestions, let us know through <a href=\"https:\/\/visualstudio.uservoice.com\/forums\/121579-visual-studio-2015\/category\/30937-languages-c\">UserVoice<\/a>. Thank you!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Throughout the VS 2015 cycle we&#8217;ve been focusing on the quality of our expression SFINAE implementation. Because expression SFINAE issues can be subtle and complex we&#8217;ve been using popular libraries such as Boost and Microsoft&#8217;s fork of Range-v3\u00a0to validate our implementation and find remaining bugs. As we shift the compiler team&#8217;s focus to Visual Studio [&hellip;]<\/p>\n","protected":false},"author":312,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[270],"tags":[100,116,248,323],"class_list":["post-10615","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-announcement","tag-c-language","tag-c11","tag-expression-sfinae","tag-sfinae"],"acf":[],"blog_post_summary":"<p>Throughout the VS 2015 cycle we&#8217;ve been focusing on the quality of our expression SFINAE implementation. Because expression SFINAE issues can be subtle and complex we&#8217;ve been using popular libraries such as Boost and Microsoft&#8217;s fork of Range-v3\u00a0to validate our implementation and find remaining bugs. As we shift the compiler team&#8217;s focus to Visual Studio [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/10615","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/312"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=10615"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/10615\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=10615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=10615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=10615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}