Modify

Ticket #10443 (closed Bugs: fixed)

Opened 3 years ago

Last modified 22 months ago

[fusion] Compile errors with boost::fusion::invoke and boost::result_of using decltype

Reported by: James Whitworth <fun4jimmy@…> Owned by: djowel
Milestone: To Be Determined Component: fusion
Version: Boost 1.56.0 Severity: Problem
Keywords: invoke result_of delctype c++11 Cc: jaredgrubb@…, flast@…

Description

The following example fails to compile with c++11 compliant compilers.

#include <boost/bind.hpp>
#include <boost/function.hpp>

#include <boost/fusion/functional.hpp>

void Function( int & output )
{
  output = 12;
}

int main( int, char ** )
{
  boost::fusion::vector1< int > parameters;
  boost::function< void( int & ) > function = &Function;

  boost::fusion::invoke( function, parameters );

  return 0;
}

I think the problem is due to the implementation boost::result using decltype and boost::fusion::invoke expecting the old TR1 type behaviour. The example compiles fine when BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK is defined.

Compiling the above with clang++ -std=c++11 main.cpp generates the following output:

In file included from main.cpp:4:
In file included from /usr/local/include/boost/fusion/functional.hpp:13:
In file included from /usr/local/include/boost/fusion/functional/invocation.hpp:13:
In file included from /usr/local/include/boost/fusion/functional/invocation/invoke.hpp:96:
In file included from /usr/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:
/usr/local/include/boost/fusion/functional/invocation/invoke.hpp:205:55: error: no type named 'type' in 'boost::result_of<boost::function<void (int &)> (const int &)>'
                    Function(BOOST_PP_ENUM(N,M,~)) >::type result_type;
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/usr/local/include/boost/fusion/functional/invocation/invoke.hpp:161:38: note: in instantiation of template class 'boost::fusion::detail::invoke_impl<boost::function<void (int &)>, const boost::fusion::vector1<int>, 1, false, true>' requested here
            typedef typename detail::invoke_impl<
                                     ^
/usr/local/include/boost/fusion/functional/invocation/invoke.hpp:179:32: note: in instantiation of template class 'boost::fusion::result_of::invoke<boost::function<void (int &)>, const boost::fusion::vector1<int> >' requested here
    inline typename result_of::invoke<Function,Sequence const>::type
                               ^
/usr/local/include/boost/fusion/functional/invocation/invoke.hpp:180:5: note: while substituting deduced template arguments into function template 'invoke' [with Function = boost::function<void (int &)>, Sequence = boost::fusion::vector1<int>]
    invoke(Function f, Sequence const & s)
    ^
1 error generated.

Attachments

Change History

comment:1 Changed 3 years ago by James Whitworth <fun4jimmy@…>

comment:2 Changed 3 years ago by James Whitworth <fun4jimmy@…>

  • Summary changed from Compile errors with boost::fusion::invoke and boost::result_of using decltype to [fusion] Compile errors with boost::fusion::invoke and boost::result_of using decltype

comment:3 Changed 3 years ago by Agustín K-ballo Bergé <kaballo86@…>

We have discussed this on IRC with alfC, and come to the conclusion that the underlying issue is that result_of::invoke is not SFINAE-friendly (as defined by C++11). The proper fix for this issue is then to make it SFINAE-friendly for all C++ versions.

Additionally, there are two invoke definitions: one for Sequence& and another one for Sequence const&. This is redundant at best, and should be simplified.

comment:4 Changed 3 years ago by michel

I've not followed recent updates in Boost.Fusion, so I might be wrong, but...

Both C++03 and C++11 versions of fusion::invoke are not SFINAE-friendly, as demonstrated in this post (  Re: [result_of] now uses decltype on release branch ):

#include <boost/fusion/include/invoke.hpp>
#include <boost/fusion/include/vector.hpp>

struct F {
    template <typename Sig>
    struct result;
    template <typename This>
    struct result<This(int&)>
    {
        typedef void type;
    };
    void operator()(int&) const {}
};

int main (int argc, char* argv[])
{
    boost::fusion::vector<int> v(1);

    // Error;
    // trying to instantiate result_of<F(const int&)>
    boost::fusion::invoke(F(), v);

    return 0;
}

comment:5 Changed 2 years ago by Jared Grubb <jaredgrubb@…>

Note I hit a very similar issue (#10676) with boost::fusion::fold. I think there's a general issue with fusion's "result_of" detail classes (boost::fusion::result_of::Stuff) not being SFINAE compatible.

comment:6 Changed 2 years ago by Jared Grubb <jaredgrubb@…>

  • Cc jaredgrubb@… added

comment:7 Changed 2 years ago by djowel

  • Status changed from new to closed
  • Resolution set to fixed

Fixed now in develop branch. invoke is now sfinae friendly. Please check to be sure.

comment:8 Changed 2 years ago by Kohei Takahashi <flast@…>

  • Cc flast@… added
  • Status changed from closed to reopened
  • Resolution fixed deleted

I think djowel's fix is incomplete. I open a pull-request to fix this issue completely.

Please check it. ttps://github.com/boostorg/fusion/pull/24

comment:9 Changed 22 months ago by djowel

  • Status changed from reopened to closed
  • Resolution set to fixed
View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.