Opened 10 years ago

Closed 10 years ago

#6915 closed Bugs (fixed)

boost::fusion::result_of::invoke compilation errors

Reported by: ulidtko@… Owned by: Joel de Guzman
Milestone: To Be Determined Component: fusion
Version: Boost 1.49.0 Severity: Problem
Keywords: Cc:

Description

In Boost.Fusion 1.49.0, boost::fusion::result_of::invoke metafunction causes compilation errors in some cases of SFINAE usage.

See attachments for reproducing example.

Please note how the code works with trivial metafunction (subst_failure_if_not_int), and does not with boost::fusion::result_of::invoke, while being used in identical manner.

Also note that the following line:

  try_invoke<F, boost::fusion::vector<float>> (0);

may compile or not depending on the BOOST_RESULT_OF_USE_DECLTYPE switch under GCC. Which is a fair clue of that this is probably boost's bug.

Compiler error messages

MSVC 9

d:\boost\1_49_0\boost\fusion\functional\invocation\invoke.hpp(199) : error C2039: 'type' : is not a member of 'boost::result_of<F>'
d:\boost\1_49_0\boost\fusion\functional\invocation\invoke.hpp(159) : see reference to class template instantiation 'boost::fusion::detail::invoke_impl<Function,Sequence>' being compiled
..\substitution_failure_test.cpp(60) : see reference to class template instantiation 'boost::fusion::result_of::invoke<Function,Sequence>' being compiled
        with
        [
            Function=F,
            Sequence=boost::fusion::vector<float>
        ]

GCC 4.5.3

When compiling with #define BOOST_RESULT_OF_USE_DECLTYPE 1:

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<F(junk&)>’:
D:/boost/1_49_0/boost/utility/detail/result_of_iterate.hpp:52:1:   instantiated from ‘boost::result_of<F(junk&)>’
D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:199:60:   instantiated from ‘boost::fusion::detail::invoke_impl<F, boost::fusion::vector<junk>, 1, false, true>’
D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:159:30:   instantiated from ‘boost::fusion::result_of::invoke<F, boost::fusion::vector<junk> >’
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&)’
substitution_failure_test.cpp:39:6: note: candidate is: int F::operator()(float)

Without:

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<F, boost::fusion::vector<float>, 1, false, true>’:
D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:159:30:   instantiated from ‘boost::fusion::result_of::invoke<F, boost::fusion::vector<float> >’
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<F(float&)>’
D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp: In instantiation of ‘boost::fusion::detail::invoke_impl<F, boost::fusion::vector<junk>, 1, false, true>’:
D:/boost/1_49_0/boost/fusion/functional/invocation/invoke.hpp:159:30:   instantiated from ‘boost::fusion::result_of::invoke<F, boost::fusion::vector<junk> >’
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<F(junk&)>’

PS: I ♥ search engines.

Attachments (1)

substitution_failure_test.cpp (1.8 KB ) - added by ulidtko@… 10 years ago.
reproducing example

Download all attachments as: .zip

Change History (4)

by ulidtko@…, 10 years ago

reproducing example

comment:1 by viboes, 10 years ago

Component: Nonefusion
Owner: set to Joel de Guzman

comment:2 by anonymous, 10 years ago

First reported here: http://stackoverflow.com/questions/10632848/boost-fusion-invoke-and-sfinae

If fixed, closure in the form of a note on the original Stack Overflow question would be very much appreciated.

comment:3 by Joel de Guzman, 10 years ago

Resolution: fixed
Status: newclosed

I fixed this in trunk. The first test:

try_invoke<F, boost::fusion::vector<float>> (0);

now compiles just fine. The second test however is (IMO) erroneous:

try_invoke<F, boost::fusion::vector<junk>> (0);

This cannot select the fallback overload because

typename boost::fusion::result_of::invoke<F, Sequence>::type

will be erroneous and will not trigger SFINAE. The code attached is equivalent to this:

#include <boost/utility/result_of.hpp> #include <iostream>

int foo(int); struct junk {};

template <typename F, typename Arg> typename boost::result_of<F(Arg)>::type call(int) {

return F(Arg());

}

template <typename F, typename Arg> void call(long) {

fallback std::cout << "fallback" << std::endl;

}

int main() {

call<int(*)(int), junk>(123);

}

which will give you an error. Notice though that if I replace:

typename boost::result_of<F(Arg)>::type

with

decltype(F(Arg()))

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.

I'm closing this one.

Note: See TracTickets for help on using tickets.