Boost C++ Libraries: Ticket #6915: boost::fusion::result_of::invoke compilation errors https://svn.boost.org/trac10/ticket/6915 <p> In Boost.Fusion 1.49.0, <code>boost::fusion::result_of::invoke</code> metafunction causes compilation errors in some cases of SFINAE usage. </p> <p> See attachments for reproducing example. </p> <p> Please note how the code works with trivial metafunction (<code>subst_failure_if_not_int</code>), and does not with <code>boost::fusion::result_of::invoke</code>, while being used in identical manner. </p> <p> Also note that the following line: </p> <pre class="wiki"> try_invoke&lt;F, boost::fusion::vector&lt;float&gt;&gt; (0); </pre><blockquote> <p> may compile or not depending on the <code>BOOST_RESULT_OF_USE_DECLTYPE</code> switch under GCC. Which is a fair clue of that this is probably boost's bug. </p> </blockquote> <h2 class="section" id="Compilererrormessages">Compiler error messages</h2> <h3 class="section" id="MSVC9">MSVC 9</h3> <pre class="wiki">d:\boost\1_49_0\boost\fusion\functional\invocation\invoke.hpp(199) : error C2039: 'type' : is not a member of 'boost::result_of&lt;F&gt;' d:\boost\1_49_0\boost\fusion\functional\invocation\invoke.hpp(159) : see reference to class template instantiation 'boost::fusion::detail::invoke_impl&lt;Function,Sequence&gt;' being compiled ..\substitution_failure_test.cpp(60) : see reference to class template instantiation 'boost::fusion::result_of::invoke&lt;Function,Sequence&gt;' being compiled with [ Function=F, Sequence=boost::fusion::vector&lt;float&gt; ] </pre><h3 class="section" id="GCC4.5.3">GCC 4.5.3</h3> <p> When compiling with <code>#define BOOST_RESULT_OF_USE_DECLTYPE 1</code>: </p> <pre class="wiki">In file included from D:/boost/1_49_0/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0, from D:/boost/1_49_0/boost/utility/result_of.hpp:95, from D:/boost/1_49_0/boost/fusion/support/detail/segmented_fold_until_impl.hpp:13, from D:/boost/1_49_0/boost/fusion/sequence/intrinsic/detail/segmented_begin_impl.hpp:15, from D:/boost/1_49_0/boost/fusion/sequence/intrinsic/detail/segmented_begin.hpp:10, from D:/boost/1_49_0/boost/fusion/sequence/intrinsic/begin.hpp:17, from D:/boost/1_49_0/boost/fusion/container/vector/vector10.hpp:15, from D:/boost/1_49_0/boost/fusion/container/vector.hpp:12, from D:/boost/1_49_0/boost/fusion/container.hpp:10, from substitution_failure_test.cpp:5: D:/boost/1_49_0/boost/utility/detail/result_of_iterate.hpp: In instantiation of ‘boost::detail::cpp0x_result_of_impl&lt;F(junk&amp;)&gt;’: D:/boost/1_49_0/boost/utility/detail/result_of_iterate.hpp:52:1: instantiated from ‘boost::result_of&lt;F(junk&amp;)&gt;’ D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:199:60: instantiated from ‘boost::fusion::detail::invoke_impl&lt;F, boost::fusion::vector&lt;junk&gt;, 1, false, true&gt;’ D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:159:30: instantiated from ‘boost::fusion::result_of::invoke&lt;F, boost::fusion::vector&lt;junk&gt; &gt;’ substitution_failure_test.cpp:65:47: instantiated from here D:/boost/1_49_0/boost/utility/detail/result_of_iterate.hpp:64:5: error: no match for call to ‘(F) (junk&amp;)’ substitution_failure_test.cpp:39:6: note: candidate is: int F::operator()(float) </pre><p> Without: </p> <pre class="wiki">In file included from D:/boost/1_49_0/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0, from D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:93, from D:/boost/1_49_0/boost/fusion/functional/invocation.hpp:12, from D:/boost/1_49_0/boost/fusion/functional.hpp:12, from substitution_failure_test.cpp:7: D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp: In instantiation of ‘boost::fusion::detail::invoke_impl&lt;F, boost::fusion::vector&lt;float&gt;, 1, false, true&gt;’: D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:159:30: instantiated from ‘boost::fusion::result_of::invoke&lt;F, boost::fusion::vector&lt;float&gt; &gt;’ substitution_failure_test.cpp:62:48: instantiated from here D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:199:60: error: no type named ‘type’ in ‘struct boost::result_of&lt;F(float&amp;)&gt;’ D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp: In instantiation of ‘boost::fusion::detail::invoke_impl&lt;F, boost::fusion::vector&lt;junk&gt;, 1, false, true&gt;’: D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:159:30: instantiated from ‘boost::fusion::result_of::invoke&lt;F, boost::fusion::vector&lt;junk&gt; &gt;’ substitution_failure_test.cpp:65:47: instantiated from here D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:199:60: error: no type named ‘type’ in ‘struct boost::result_of&lt;F(junk&amp;)&gt;’ </pre><p> <sub>PS: <em>I ♥ search engines.</em></sub> </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/6915 Trac 1.4.3 ulidtko@… Thu, 17 May 2012 17:39:54 GMT attachment set https://svn.boost.org/trac10/ticket/6915 https://svn.boost.org/trac10/ticket/6915 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">substitution_failure_test.cpp</span> </li> </ul> <p> reproducing example </p> Ticket viboes Mon, 28 May 2012 17:15:41 GMT component changed; owner set https://svn.boost.org/trac10/ticket/6915#comment:1 https://svn.boost.org/trac10/ticket/6915#comment:1 <ul> <li><strong>owner</strong> set to <span class="trac-author">Joel de Guzman</span> </li> <li><strong>component</strong> <span class="trac-field-old">None</span> → <span class="trac-field-new">fusion</span> </li> </ul> Ticket anonymous Thu, 21 Jun 2012 09:27:17 GMT <link>https://svn.boost.org/trac10/ticket/6915#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6915#comment:2</guid> <description> <p> First reported here: <a class="ext-link" href="http://stackoverflow.com/questions/10632848/boost-fusion-invoke-and-sfinae"><span class="icon">​</span>http://stackoverflow.com/questions/10632848/boost-fusion-invoke-and-sfinae</a> </p> <p> If fixed, closure in the form of a note on the original Stack Overflow question would be very much appreciated. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Joel de Guzman</dc:creator> <pubDate>Tue, 04 Sep 2012 15:04:17 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/6915#comment:3 https://svn.boost.org/trac10/ticket/6915#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> I fixed this in trunk. The first test: </p> <blockquote> <p> try_invoke&lt;F, boost::fusion::vector&lt;float&gt;&gt; (0); </p> </blockquote> <p> now compiles just fine. The second test however is (IMO) erroneous: </p> <blockquote> <p> try_invoke&lt;F, boost::fusion::vector&lt;junk&gt;&gt; (0); </p> </blockquote> <p> This cannot select the fallback overload because </p> <blockquote> <p> typename boost::fusion::result_of::invoke&lt;F, Sequence&gt;::type </p> </blockquote> <p> will be erroneous and will not trigger SFINAE. The code attached is equivalent to this: </p> <blockquote> <p> #include &lt;boost/utility/result_of.hpp&gt; #include &lt;iostream&gt; </p> </blockquote> <blockquote> <p> int foo(int); struct junk {}; </p> </blockquote> <blockquote> <p> template &lt;typename F, typename Arg&gt; typename boost::result_of&lt;F(Arg)&gt;::type call(int) { </p> <blockquote> <p> return F(Arg()); </p> </blockquote> <p> } </p> </blockquote> <blockquote> <p> template &lt;typename F, typename Arg&gt; void call(long) { </p> <blockquote> <p> <em> fallback std::cout &lt;&lt; "fallback" &lt;&lt; std::endl; </em></p> </blockquote> <p> } </p> </blockquote> <blockquote> <p> int main() { </p> <blockquote> <p> call&lt;int(*)(int), junk&gt;(123); </p> </blockquote> <p> } </p> </blockquote> <p> which will give you an error. Notice though that if I replace: </p> <blockquote> <p> typename boost::result_of&lt;F(Arg)&gt;::type </p> </blockquote> <p> with </p> <blockquote> <p> decltype(F(Arg())) </p> </blockquote> <p> then it works. So the question now falls into the hands of the Boost::result_of maintainers. If you think this should work, then, go add a ticket to boost::result_of. </p> <p> I'm closing this one. </p> Ticket