Boost C++ Libraries: Ticket #7343: Extend result_of to work with SFINAE https://svn.boost.org/trac10/ticket/7343 <p> In response to a problem first identified by Joel de Guzman: </p> <p> <a class="ext-link" href="http://thread.gmane.org/gmane.comp.lib.boost.devel/233752/focus=233934"><span class="icon">​</span>http://thread.gmane.org/gmane.comp.lib.boost.devel/233752/focus=233934</a> </p> <p> When BOOST_RESULT_OF_USE_DECLTYPE is defined, the attached patch makes the expression result_of&lt;Fn( <a class="missing wiki">ArgTypes</a> ...)&gt;::type not well formed when the expression decltype(INVOKE(declval&lt; Fn &gt;(), declval&lt; <a class="missing wiki">ArgTypes</a> &gt;()...)) is not well formed, but does not break SFINAE when used as the return type of a function overload. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/7343 Trac 1.4.3 Daniel Walker Fri, 07 Sep 2012 03:28:24 GMT attachment set https://svn.boost.org/trac10/ticket/7343 https://svn.boost.org/trac10/ticket/7343 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">djw_result_of_sfinae.patch</span> </li> </ul> <p> updated patch incorporating suggestions from Michel Morin </p> Ticket Eric Niebler Wed, 19 Sep 2012 17:26:27 GMT attachment set https://svn.boost.org/trac10/ticket/7343 https://svn.boost.org/trac10/ticket/7343 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">ean_result_of_sfinae.patch</span> </li> </ul> <p> simpler patch, tested with clang-trunk </p> Ticket Eric Niebler Wed, 19 Sep 2012 17:33:44 GMT <link>https://svn.boost.org/trac10/ticket/7343#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:1</guid> <description> <p> Daniel, I've attached a much simpler, lighter-weight patch. However, both of our patches are incomplete because of how <code>result_of</code> is defined: </p> <pre class="wiki">// Uses declval following N3225 20.7.7.6 when F is not a pointer. template&lt;typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)&gt; struct result_of&lt;F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))&gt; : mpl::if_&lt; is_member_function_pointer&lt;F&gt; , detail::tr1_result_of_impl&lt; typename remove_cv&lt;F&gt;::type, typename remove_cv&lt;F&gt;::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false &gt; , detail::cpp0x_result_of_impl&lt; F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)) &gt; &gt;::type {}; </pre><p> If <code>F</code> is a member function pointer, the first branch of the <code>mpl::if_</code> gets taken, and no clever SFINAE guards <code>detail::tr1_result_of_impl</code>. </p> <p> But to a first approximation, I think this is good enough for 1.52. I tested my patch with clang-trunk, but not the most recent stable release, and not with msvc-11, which I'm downloading now. If you have access to those and want to get a jump on things, that'd be great. I'd like to get this change in to trunk ASAP so we have time to merge to release for 1.52. </p> <p> Thanks for your work on this. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Daniel Walker</dc:creator> <pubDate>Wed, 19 Sep 2012 17:55:21 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:2</guid> <description> <p> Thanks Eric. Your patch looks reasonable, and I like the simplifications. I'll test on clang 2.1 later today and assuming all's well I'll check your patch into trunk. I'd also like to see this in the 1.52 release. To my knowledge this is not a breaking change, i.e. enabling SFINAE doesn't invalidate any previously valid code, so we should be good to go. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Wed, 19 Sep 2012 20:47:11 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:3</guid> <description> <p> Sadly, my patch doesn't work with msvc-11, but yours does. Unfortunately, yours has heavier TMP overhead. The best solution, IMO, would be to use yours for msvc-11 and use mine in other cases, assuming clang 3.1 can handle it. Thoughts? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Wed, 19 Sep 2012 21:06:30 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:4</guid> <description> <p> For the record, here is the msvc bug that is blocking the simpler implementation from working: </p> <p> <a class="ext-link" href="https://connect.microsoft.com/VisualStudio/feedback/details/763618/too-eager-instantiation-in-class-template-partial-specialization"><span class="icon">​</span>https://connect.microsoft.com/VisualStudio/feedback/details/763618/too-eager-instantiation-in-class-template-partial-specialization</a> </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Wed, 19 Sep 2012 22:01:11 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:5</guid> <description> <p> I tested both versions (in a C++11 mode with <code>BOOST_RESULT_OF_USE_DECLTYPE</code>) and got the same results: </p> <ul><li>gcc 4.3-4.4: compilation error on sfinae_test </li><li>gcc 4.5-4.7, 4.8 (experimental): OK </li><li>clang 2.8-3.1, 3.2 (trunk): OK </li></ul><p> I think gcc 4.3-4.4 had incomplete support of "SFINAE for expressions" (though <code>BOOST_NO_SFINAE_EXPR</code> is not defined on gcc 4.4). </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Daniel Walker</dc:creator> <pubDate>Wed, 19 Sep 2012 23:17:47 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:6</guid> <description> <p> I combined the two patches so that the thin implementation is the default and the is_callable implementation is a workaround for MSVC tested at 1700. I tested on clang 3.2 and gcc 4.7 with BOOST_RESULT_OF_USE_DECLTYPE and can corroborate Michel's results. Eric could you test on MSVC one more time? If everything is OK, I think its ready to merge to release. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Wed, 19 Sep 2012 23:31:37 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:7</guid> <description> <p> I tested <a class="changeset" href="https://svn.boost.org/trac10/changeset/80605" title="SFINAE enabled result_of fixes [7343]">r80605</a> (in a C++11 mode with BOOST_RESULT_OF_USE_DECLTYPE). The test results are the same as above: </p> <ul><li>gcc 4.3-4.4: compilation error on sfinae_test </li><li>gcc 4.5-4.7, 4.8 (experimental): OK </li><li>clang 2.8-3.1, 3.2 (trunk): OK </li></ul> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Thu, 20 Sep 2012 06:06:36 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:8</guid> <description> <p> Tests pass on msvc 8-11. That does *not* mean we're ready to merge to release, though. It means we're ready to wait and see what crops up in the trunk regression reports. :-) </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Thu, 20 Sep 2012 12:09:00 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:9</guid> <description> <p> I can see a tab in line 124 of <code>result_of_iterate.hpp</code> ;-) </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Thu, 20 Sep 2012 17:10:10 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:10</guid> <description> <p> Bah. My bad. Fixed in <a class="changeset" href="https://svn.boost.org/trac10/changeset/80608" title="untab-ify">[80608]</a>. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Fri, 21 Sep 2012 11:11:11 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:11 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:11</guid> <description> <p> Eric, did you test on msvc 10 with <code>BOOST_RESULT_OF_USE_DECLTYPE</code>? (In other word, does the "Too-eager instantiation in class template partial specialization" bug happen only on msvc 11?) </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Fri, 21 Sep 2012 18:57:16 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:12 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:12</guid> <description> <p> Good question. No, it doesn't compile on msvc 10 in that configuration. I'll look into it. </p> <p> Regardless, I took the liberty of merging all the outstanding result_of changes to release, since the trunk tests looked no worse than before. When I get a handle on the msvc regression, I'll merge that too. For reference, the release changeset is <a class="changeset" href="https://svn.boost.org/trac10/changeset/80621" title="result_of: merge [80445], [80452], [80535], [80550], [80605], [80608] ...">[80621]</a>. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Sat, 22 Sep 2012 19:18:57 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:13 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:13</guid> <description> <p> Changeset <a class="changeset" href="https://svn.boost.org/trac10/changeset/80636" title="sfinae-friendly result_of implementation for compilers that don't have ...">[80636]</a> on trunk changes the workaround for msvc and extends it to work for all compilers that don't do extended-sfinae-for-expressions. All the tests should pass now, even on gcc 4.3-4.4. Michel, can you give it a shot? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Daniel Walker</dc:creator> <pubDate>Sat, 22 Sep 2012 23:55:43 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:14 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:14</guid> <description> <p> Works on gcc 4.4. Nice! However, BOOST_NO_SFINAE_EXPR does not appear to be defined for 4.4. boost/config/gcc.hpp has </p> <table class="wiki"> <tr>#if <span class="underline">GNUC</span> &lt; 4 <td> (<span class="underline">GNUC</span> == 4 &amp;&amp; <span class="underline">GNUC_MINOR</span> &lt; 4) </td></tr></table> <p> # define BOOST_NO_SFINAE_EXPR #endif </p> <p> Should that be <span class="underline">GNUC_MINOR</span> &lt; 5? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Sun, 23 Sep 2012 00:16:49 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:15 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:15</guid> <description> <p> I don't know. What's your reason for thinking that <code>BOOST_NO_SFINAE_EXPR</code> should be defined for gcc 4.4? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Daniel Walker</dc:creator> <pubDate>Sun, 23 Sep 2012 00:46:25 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:16 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:16</guid> <description> <p> I don't know either, but you ifdefed the workaround with BOOST_NO_SFINAE_EXPR. I had to define it in order to test your changes, which do work on gcc 4.4. The tests fail on gcc 4.4 without the workaround. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Sun, 23 Sep 2012 00:50:57 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:17 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:17</guid> <description> <p> First, I did the following </p> <ol><li>Remove <code>BOOST_RESULT_OF_USE_DECLTYPE</code> guard for <code>sfinae_test</code> in <code>result_of_test.cpp</code>. </li><li>Make gcc 4.4 in a C++11 mode (with <code>BOOST_RESULT_OF_USE_DECLTYPE</code>) follow the <code>BOOST_NO_SFINAE_EXPR</code> branch. </li></ol><p> Without applying 2, the test fails to compile on gcc 4.4 (in a C++11 mode <code>BOOST_RESULT_OF_USE_DECLTYPE</code>). </p> <p> Here are the test results. </p> <ul><li>gcc 4.3 - 4.8 (in a C++03 mode): OK </li><li>gcc 4.3 - 4.8 (in a C++11 mode): OK </li><li>gcc 4.3 - 4.4 (in a C++11 mode + BOOST_RESULT_OF_USE_DECLTYPE): OK but with two warnings: <pre class="wiki">boost/utility/detail/result_of_iterate.hpp:100: warning: object of type 'volatile int&amp;' will not be accessed in left-hand operand of comma </pre><pre class="wiki">boost/utility/detail/result_of_iterate.hpp:100: warning: object of type 'const volatile int&amp;' will not be accessed in left-hand operand of comma </pre></li><li>gcc 4.5 - 4.8 (in a C++11 mode + BOOST_RESULT_OF_USE_DECLTYPE): OK </li></ul><ul><li>clang 2.8 - 3.2 (in a C++03 mode): OK </li><li>clang 2.8 - 3.2 (in a C++11 mode): OK </li><li>clang 2.8 - 3.2 (in a C++11 mode + BOOST_RESULT_OF_USE_DECLTYPE): OK </li></ul> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Sun, 23 Sep 2012 00:51:44 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:18 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:18</guid> <description> <p> Full warning messages on gcc 4.3-4.4 (in a C++11 mode <code>BOOST_RESULT_OF_USE_DECLTYPE</code>): </p> <pre class="wiki">boost/utility/detail/result_of_iterate.hpp: In instantiation of 'const bool boost::detail::result_of_is_callable_2&lt;result_of_member_function_template, volatile int&amp;, int&gt;::value': boost/utility/detail/result_of_iterate.hpp:101: instantiated from 'boost::detail::result_of_is_callable_2&lt;result_of_member_function_template, volatile int&amp;, int&gt;' boost/utility/enable_if.hpp:47: instantiated from 'boost::lazy_enable_if&lt;boost::detail::result_of_is_callable_2&lt;result_of_member_function_template, volatile int&amp;, int&gt;, boost::detail::cpp0x_result_of_impl&lt;result_of_member_function_template ()(volatile int&amp;, int), false&gt; &gt;' boost/utility/result_of.hpp:118: instantiated from 'boost::detail::cpp0x_result_of_impl&lt;result_of_member_function_template ()(volatile int&amp;, int), true&gt;' boost/utility/result_of.hpp:59: instantiated from 'boost::result_of&lt;result_of_member_function_template ()(volatile int&amp;, int)&gt;' untitled:245: instantiated from here boost/utility/detail/result_of_iterate.hpp:100: warning: object of type 'volatile int&amp;' will not be accessed in left-hand operand of comma boost/utility/detail/result_of_iterate.hpp: In instantiation of 'const bool boost::detail::result_of_is_callable_2&lt;result_of_member_function_template, const volatile int&amp;, int&gt;::value': boost/utility/detail/result_of_iterate.hpp:101: instantiated from 'boost::detail::result_of_is_callable_2&lt;result_of_member_function_template, const volatile int&amp;, int&gt;' boost/utility/enable_if.hpp:47: instantiated from 'boost::lazy_enable_if&lt;boost::detail::result_of_is_callable_2&lt;result_of_member_function_template, const volatile int&amp;, int&gt;, boost::detail::cpp0x_result_of_impl&lt;result_of_member_function_template ()(const volatile int&amp;, int), false&gt; &gt;' boost/utility/result_of.hpp:118: instantiated from 'boost::detail::cpp0x_result_of_impl&lt;result_of_member_function_template ()(const volatile int&amp;, int), true&gt;' boost/utility/result_of.hpp:59: instantiated from 'boost::result_of&lt;result_of_member_function_template ()(const volatile int&amp;, int)&gt;' untitled:246: instantiated from here boost/utility/detail/result_of_iterate.hpp:100: warning: object of type 'const volatile int&amp;' will not be accessed in left-hand operand of comma </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Sun, 23 Sep 2012 00:54:57 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:19 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:19</guid> <description> <p> In the above warnings, <code>untitled:***</code> means <code>result_of_test.cpp:***</code>. Sorry about that. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Sun, 23 Sep 2012 01:11:58 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:20 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:20</guid> <description> <p> Changeset <a class="changeset" href="https://svn.boost.org/trac10/changeset/80654" title="gcc-4.4 doesn't have robust enough support for sfinae-for-expressions">[80654]</a> applies the workaround to gcc-4.4 also. Can you give it a shot? And how do I suppress errors on gcc? </p> <p> EDIT: How do I suppress *WARNINGS* on gcc? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Sun, 23 Sep 2012 01:47:50 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:21 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:21</guid> <description> <p> gcc has </p> <pre class="wiki">#pragma GCC diagnostic ignored "-Wxxxx" </pre><p> but, before gcc 4.6, the following is not supported. </p> <pre class="wiki">#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wxxxx" #pragma GCC diagnostic pop </pre><p> So we cannot restore the user's warning conditions. </p> <p> Another way to disable warnings is add </p> <pre class="wiki">#pragma GCC system_header </pre><p> Adding this pragma into <code>result_of.hpp</code> or <code>result_of_iterate.hpp</code> removes the warning. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Daniel Walker</dc:creator> <pubDate>Sun, 23 Sep 2012 01:51:53 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:22 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:22</guid> <description> <p> Warnings suppressed in changeset <a class="changeset" href="https://svn.boost.org/trac10/changeset/80655" title="supress warnings in result_of_iterate.hpp on gcc 4 and up.">[80655]</a> on gcc. Thanks for all the work Eric. The users will appreciate it! And thanks for the help Michel. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Sun, 23 Sep 2012 02:10:45 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:23 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:23</guid> <description> <p> I tested <a class="changeset" href="https://svn.boost.org/trac10/changeset/80655" title="supress warnings in result_of_iterate.hpp on gcc 4 and up.">r80655</a> on gcc and clang and it works fine. </p> <p> Daniel, I think </p> <pre class="wiki">#if defined(__GNUC__) &amp;&amp; (__GNUC__ == 4) &amp;&amp; (__GNUC_MINOR__ &lt; 5) &amp;&amp; defined(BOOST_RESULT_OF_USE_DECLTYPE) #pragma GCC system_header #endif </pre><p> would be safer for the future development. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Sun, 23 Sep 2012 02:12:56 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:24 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:24</guid> <description> <p> I found a workaround for the gcc warnings in code. Changeset <a class="changeset" href="https://svn.boost.org/trac10/changeset/80656" title="nicer work-around for gcc warnings">[80656]</a> makes the change and removes the <code>#pragma GCC system_header</code>. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Sun, 23 Sep 2012 02:19:09 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7343#comment:25 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7343#comment:25</guid> <description> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/80656" title="nicer work-around for gcc warnings">r80656</a> works fine on gcc and clang. Thanks Eric and Daniel for all the work! </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Michel Morin</dc:creator> <pubDate>Tue, 25 Sep 2012 13:59:42 GMT</pubDate> <title>component changed https://svn.boost.org/trac10/ticket/7343#comment:26 https://svn.boost.org/trac10/ticket/7343#comment:26 <ul> <li><strong>component</strong> <span class="trac-field-old">utility</span> → <span class="trac-field-new">result_of</span> </li> </ul> Ticket