4

The following code does not compile on g++ (GCC) 4.6.0 20110603 (prerelease) with -std=c++0x and Boost 1.46.1. Am I missing an include or is this actually a bug? If the latter, how to work around it?

#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/clear.hpp>

#include <boost/fusion/mpl.hpp>
#include <boost/fusion/include/clear.hpp>
#include <boost/fusion/include/clear.hpp>

#include <boost/fusion/adapted/boost_tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>

namespace mpl = boost::mpl;

template<typename T>
struct Meta {
  T t;
  typedef mpl::vector<std::function<void(double)>, std::function<void(char)>, 
              std::function<void(int)>> MplVector;
  typedef T FusionSequence;

  //works
  typedef mpl::transform< MplVector, mpl::identity<mpl::_1> >::type result;
  //doesn't, work
  typedef typename mpl::transform< FusionSequence, mpl::identity<mpl::_1> >::type result2;
};

template<typename T>
Meta<T> make_meta(T t) { return Meta<T>({t}); }

int main()
{
  auto m = make_meta(boost::make_tuple(
               std::function<void(double)>([](double) { }),
               std::function<void(int)>([](int) { }),
               std::function<void(char)>([](char) { })));
}
Luc Touraille
  • 79,925
  • 15
  • 92
  • 137
pmr
  • 58,701
  • 10
  • 113
  • 156
  • 1
    looks like that `transform` has to instantiate `mpl::clear`, which succeeds for MplVector but fails for FusionSequence because there are only clears for list, map, set, vector, and deque in `boost/fusion/mpl/detail/clear.hpp`? No idea about workarounds though. – Cubbi Jun 21 '11 at 16:29
  • @Cubbi I guessed as much but fail to understand why transform would clear the sequence. As far as I known transform only requires a `ForwardSequence` and `tupleS` conform to this. `transform` used to require an `ExtensibleSequence` maybe that bit is inherited from an older version. I highly doubt it, though. – pmr Jun 21 '11 at 16:37

2 Answers2

4

When you do not provide an inserter, transform has to generate one for you (the result has to be accumulated somewhere), which essentially amounts to doing something like back_inserter< clear<OriginalSequence>::type >. The transform docs are somewhat misleading here since they do not document this extra requirement for the "no-inserter" versions of the algorithm.

agurtovoy
  • 260
  • 1
  • 5
2

If you use fusion::make_vector instead of make_tuple, you could use mpl::tranform. The critical trick is to also #include <boost/fusion/include/transform.hpp>! A simple example is as follows:

#include <boost/fusion/include/transform.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/mpl/transform.hpp>

// Only works if <boost/fusion/include/transform.hpp> is included:
typedef boost::fusion::vector<int> FusionVector;
typedef typename boost::mpl::transform<FusionVector, boost::mpl::_1>::type FusionTransformed;
hrr
  • 1,807
  • 2
  • 21
  • 35