2

Trying to compile the following call to boost::fusion::invoke in boost-1.56 fails in Visual Studio 2013 but there is no error when compiling with Visual Studio 2012.

#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;
}

The compiler output is:

boost\fusion\functional\invocation\invoke.hpp(205): error C2039: 'type' : is not a member of 'boost::result_of<Function (const int &)>'
    with
    [
        Function=boost::function<void (int &)>
    ]
    boost\fusion\functional\invocation\invoke.hpp(163) : see reference to class template instantiation 'boost::fusion::detail::invoke_impl<boost::function<void (int &)>,Sequence,1,false,true>' being compiled
    with
    [
        Sequence=const boost::fusion::vector1<int>
    ]
    main.cpp(16) : see reference to class template instantiation 'boost::fusion::result_of::invoke<boost::function<void (int &)>,const boost::fusion::vector1<int>>' being compiled

It's failing when trying to instantiate boost::result_of with a const Sequence. I've looked in boost\fusion\functional\invocation\invoke.hpp and there are two overloads of boost::fusion::invoke, one is const and the other is non-const.

I think that the Visual Studio 2013 compiler is attempting to instantiate the const version even though that is not the one that should be called. If I comment out the const version in invoke.hpp the example compiles fine.

Is this a bug with Visual Studio 2013 or boost-1.56?

Is there any workaround for this problem without modifying the boost sources?

fun4jimmy
  • 672
  • 4
  • 16
  • In Visual studio 2012 and boost 1.55 it compiles fine. – Yochai Timmer Sep 02 '14 at 11:01
  • I'm sorry I don't know enough about the problem to give an authoritative answer (I'd say the bug was in VS2012), but I have checked your program on Coliru and found that both g++ and clang++ also give errors when using c++11. In case they help, the following (slightly modified) approaches work with g++/clang++ c++11/no-c++11: [Output argument](http://coliru.stacked-crooked.com/a/3d1befe31ffa9d83) and [Input argument](http://coliru.stacked-crooked.com/a/5c5743308be9ecb7). – llonesmiz Sep 02 '14 at 11:26
  • @cv_and_he Thanks. Your output argument solution works but unfortunately this was just a stripped down example of the problem. In the real world version we can't have a fusion vector with references as there are no values to initialise them with. – fun4jimmy Sep 02 '14 at 11:53

1 Answers1

5

I suspect the default for BOOST_RESULT_OF has changed for VS2013.

#define BOOST_RESULT_OF_USE_TR1

makes it compile. Chances are this bug is known and has been fixed in trunk, but you might want to report it still

sehe
  • 374,641
  • 47
  • 450
  • 633
  • PS. There's also `BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK` in case you also need a modern library that was never developed/tested with the TR1 style of RESULT_OF protocol – sehe Sep 02 '14 at 12:03
  • I found [this commit](https://github.com/boostorg/utility/commit/de0e18ca0a2bd10d54c7fc0e99adbaab98ce657f) that references the `BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK` define but you still have to manually define it. I'm not sure if this means that it is a known bug or not though. Where should I report this? – fun4jimmy Sep 02 '14 at 12:23
  • Like I said, I think it's a compiler-dependent config. VS2013 has `decltype` and apparently it supports the RESULT_OF implementation now. However, some libraries (phoenix v2 (part of spirit) comes to mind, apparently fusion too and perhaps some older libs like mpl/bind) just assume that the TR1 protocol is still followed and they will just not work without e.g. nested `result_type` typedefs. I think the bug is with the libraries that cease to work with `decltype` instead of `TR1` emulation, as `decltype` is clearly the future – sehe Sep 02 '14 at 12:51
  • 1
    I searched for an open ticket with this problem but couldn't find anything so I've reported the issue with the example code attached. https://svn.boost.org/trac/boost/ticket/10443 – fun4jimmy Sep 02 '14 at 14:21
  • This solves the issue in `clang` and `gcc`. I don't know why C++11 prefer the `invoke(Function f, Sequence const& s)` version of the function even if the passed argument is not `const` (do you know why? I has to do with the template nature of the deduced return type). Second, I also found that removing `invoke(Function f, Sequence const & s)` altogether from `invoke.hpp` solves the problem (and works in C++11 & C++98), which raises another question: why the `const` version was written in the first place? Since the previos `invoke` can also deduce the `const` part (maybe was for compatibility?) – alfC Sep 03 '14 at 06:31