Opened 8 years ago

Closed 7 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: Joel de Guzman
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.

Change History (9)

comment:1 by James Whitworth <fun4jimmy@…>, 8 years ago

comment:2 by James Whitworth <fun4jimmy@…>, 8 years ago

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

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

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 by Michel Morin, 8 years ago

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

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

Cc: jaredgrubb@… added

comment:7 by Joel de Guzman, 8 years ago

Resolution: fixed
Status: newclosed

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

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

Cc: flast@… added
Resolution: fixed
Status: closedreopened

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 by Joel de Guzman, 7 years ago

Resolution: fixed
Status: reopenedclosed
Note: See TracTickets for help on using tickets.