Modify

Opened 3 years ago

Closed 2 years ago

#10443 closed Bugs (fixed)

[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 (0)

Change History (9)

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 3 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 3 years ago by Jared Grubb <jaredgrubb@…>

  • Cc jaredgrubb@… added

comment:7 Changed 3 years ago by djowel

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

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

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

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

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 2 years ago by djowel

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

Add Comment

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain djowel.
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.