Boost fusion/mpl issues after upgrade to a newer version

一笑奈何 提交于 2019-12-24 07:18:16

问题


This is a simplified version of some code I wrote:

#include <iostream>

#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/fusion/include/filter_if.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/pair.hpp>
#include <boost/fusion/include/io.hpp>

namespace ids{
  struct a0{};
  struct a1{};
  struct a2{};
  struct a3{};
};

typedef boost::fusion::map< boost::fusion::pair<ids::a0,int>
                          , boost::fusion::pair<ids::a1,double>
                          , boost::fusion::pair<ids::a2,char>
                          , boost::fusion::pair<ids::a3,long> > map_type;

typedef boost::mpl::vector<ids::a0,ids::a3> vec_ids_type;

template <typename T>
struct get_first
{
  typedef typename T::first_type type;
};


typedef boost::fusion::result_of::filter_if<
          map_type
        , boost::mpl::contains<
            vec_ids_type
          , get_first<
              boost::mpl::placeholders::_1
            >
          >
        >::type view_type;

struct SetToZero
{
  template <typename Field>
  void operator()(Field & field) const
  {
    field.second = 0;
  }
};

int main() {
  map_type m( boost::fusion::make_pair<ids::a0>(1)
            , boost::fusion::make_pair<ids::a1>(2.0)
            , boost::fusion::make_pair<ids::a2>('a')
            , boost::fusion::make_pair<ids::a3>(4)
            );

  std::cout << m << std::endl;

  view_type v(m);
  std::cout << v << std::endl;

  boost::fusion::for_each(v,SetToZero());
  std::cout << m << std::endl;
}

I want to use view_type to set to zero some elements in an instance of map_type. If the key of one element in map_type is in vec_ids_type, then the data corresponding to that element has to be set to zero, which is done by calling the functor SetToZero. For all this to work, T is meant to be a fusion::pair when get_first<T> is instantiated.

This code compiles and runs perfectly using boost 1.40 and g++ 4.4.3. However I tried to recompile my code using newer versions of boost and g++ and I get compilation errors. Although I think it has to do with boost and not with the compiler, I'll also mention the g++ version. First I tried using boost 1.48.0.2 and g++ 4.6.3, then I tried using boost 1.49.0.1 and g++ 4.7.2. Both attempts failed, giving very similar (if not the same) compilation errors. The error messages are:

tests.cpp: In instantiation of ‘struct get_first<ids::a0>’:
/usr/include/boost/mpl/aux_/has_type.hpp:20:1:   required from ‘struct boost::mpl::aux::has_type<get_first<ids::a0>, mpl_::bool_<true> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/quote.hpp:32:36:   required from ‘struct boost::mpl::quote1<get_first, mpl_::void_>::apply<ids::a0>’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:36:8:   required from ‘struct boost::mpl::apply_wrap1<boost::mpl::quote1<get_first, mpl_::void_>, ids::a0>’
/usr/include/boost/mpl/aux_/preprocessed/gcc/bind.hpp:144:21:   [ skipping 16 instantiation contexts ]
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:101:135:   required from ‘struct boost::mpl::aux::iter_fold_if_impl<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, mpl_::na, boost::mpl::always<mpl_::bool_<false> > >’
/usr/include/boost/mpl/iter_fold_if.hpp:81:12:   required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>::result_’
/usr/include/boost/mpl/iter_fold_if.hpp:104:11:   required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>’
/usr/include/boost/mpl/find_if.hpp:39:17:   required from ‘struct boost::mpl::find_if<boost::mpl::vector<ids::a0, ids::a3>, boost::mpl::same_as<get_first<mpl_::arg<1> > > >’
/usr/include/boost/mpl/find.hpp:28:8:   required from ‘struct boost::mpl::find<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/aux_/contains_impl.hpp:33:54:   required from ‘struct boost::mpl::contains_impl<boost::mpl::aux::vector_tag>::apply<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/contains.hpp:30:8:   required from ‘struct boost::mpl::contains<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
tests.cpp:70:16:   required from here
tests.cpp:37:34: error: no type named ‘first_type’ in ‘struct ids::a0’
In file included from /usr/include/boost/mpl/assert.hpp:17:0,
                 from /usr/include/boost/mpl/aux_/na_assert.hpp:23,
                 from /usr/include/boost/mpl/arg.hpp:25,
                 from /usr/include/boost/mpl/placeholders.hpp:24,
                 from /usr/include/boost/mpl/apply.hpp:24,
                 from /usr/include/boost/mpl/aux_/iter_apply.hpp:17,
                 from /usr/include/boost/mpl/aux_/find_if_pred.hpp:14,
                 from /usr/include/boost/mpl/find_if.hpp:17,
                 from /usr/include/boost/mpl/find.hpp:17,
                 from /usr/include/boost/mpl/aux_/contains_impl.hpp:20,
                 from /usr/include/boost/mpl/contains.hpp:20,
                 from tests.cpp:12:
/usr/include/boost/mpl/not.hpp: In instantiation of ‘struct boost::mpl::not_<boost::mpl::aux::iter_apply1<boost::mpl::same_as<get_first<mpl_::arg<1> > >, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> > >’:
/usr/include/boost/mpl/aux_/nested_type_wknd.hpp:26:31:   required from ‘struct boost::mpl::aux::nested_type_wknd<boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> > >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:23:8:   required from ‘struct boost::mpl::aux::and_impl<true, boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:48:8:   required from ‘struct boost::mpl::and_<boost::mpl::not_<boost::is_same<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> > >, boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >’
/usr/include/boost/mpl/iter_fold_if.hpp:40:58:   required from ‘struct boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >::apply<void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:46:8:   required from ‘struct boost::mpl::apply_wrap2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply.hpp:67:8:   [ skipping 4 instantiation contexts ]
/usr/include/boost/mpl/iter_fold_if.hpp:104:11:   required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>’
/usr/include/boost/mpl/find_if.hpp:39:17:   required from ‘struct boost::mpl::find_if<boost::mpl::vector<ids::a0, ids::a3>, boost::mpl::same_as<get_first<mpl_::arg<1> > > >’
/usr/include/boost/mpl/find.hpp:28:8:   required from ‘struct boost::mpl::find<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/aux_/contains_impl.hpp:33:54:   required from ‘struct boost::mpl::contains_impl<boost::mpl::aux::vector_tag>::apply<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/contains.hpp:30:8:   required from ‘struct boost::mpl::contains<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
tests.cpp:70:16:   required from here
/usr/include/boost/mpl/not.hpp:39:8: error: ‘value’ is not a member of ‘boost::mpl::aux::nested_type_wknd<boost::mpl::aux::iter_apply1<boost::mpl::same_as<get_first<mpl_::arg<1> > >, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> > >’
In file included from /usr/include/boost/mpl/aux_/include_preprocessed.hpp:37:0,
                 from /usr/include/boost/mpl/and.hpp:42,
                 from /usr/include/boost/mpl/logical.hpp:18,
                 from /usr/include/boost/mpl/iter_fold_if.hpp:19,
                 from /usr/include/boost/mpl/find_if.hpp:19,
                 from /usr/include/boost/mpl/find.hpp:17,
                 from /usr/include/boost/mpl/aux_/contains_impl.hpp:20,
                 from /usr/include/boost/mpl/contains.hpp:20,
                 from tests.cpp:12:
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp: In instantiation of ‘struct boost::mpl::aux::and_impl<true, boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >’:
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:48:8:   required from ‘struct boost::mpl::and_<boost::mpl::not_<boost::is_same<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> > >, boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >’
/usr/include/boost/mpl/iter_fold_if.hpp:40:58:   required from ‘struct boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >::apply<void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:46:8:   required from ‘struct boost::mpl::apply_wrap2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply.hpp:67:8:   required from ‘struct boost::mpl::apply2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:62:63:   required from ‘struct boost::mpl::aux::iter_fold_if_forward_step<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:101:135:   [ skipping 2 instantiation contexts ]
/usr/include/boost/mpl/iter_fold_if.hpp:104:11:   required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>’
/usr/include/boost/mpl/find_if.hpp:39:17:   required from ‘struct boost::mpl::find_if<boost::mpl::vector<ids::a0, ids::a3>, boost::mpl::same_as<get_first<mpl_::arg<1> > > >’
/usr/include/boost/mpl/find.hpp:28:8:   required from ‘struct boost::mpl::find<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/aux_/contains_impl.hpp:33:54:   required from ‘struct boost::mpl::contains_impl<boost::mpl::aux::vector_tag>::apply<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/contains.hpp:30:8:   required from ‘struct boost::mpl::contains<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
tests.cpp:70:16:   required from here
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:23:8: error: ‘value’ is not a member of ‘boost::mpl::aux::nested_type_wknd<boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> > >’
In file included from /usr/include/boost/mpl/aux_/include_preprocessed.hpp:37:0,
                 from /usr/include/boost/mpl/aux_/iter_fold_if_impl.hpp:32,
                 from /usr/include/boost/mpl/iter_fold_if.hpp:25,
                 from /usr/include/boost/mpl/find_if.hpp:19,
                 from /usr/include/boost/mpl/find.hpp:17,
                 from /usr/include/boost/mpl/aux_/contains_impl.hpp:20,
                 from /usr/include/boost/mpl/contains.hpp:20,
                 from tests.cpp:12:
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp: In instantiation of ‘struct boost::mpl::aux::iter_fold_if_forward_step<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0> >’:
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:101:135:   required from ‘struct boost::mpl::aux::iter_fold_if_impl<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, mpl_::na, boost::mpl::always<mpl_::bool_<false> > >’
/usr/include/boost/mpl/iter_fold_if.hpp:81:12:   required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>::result_’
/usr/include/boost/mpl/iter_fold_if.hpp:104:11:   required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>’
/usr/include/boost/mpl/find_if.hpp:39:17:   required from ‘struct boost::mpl::find_if<boost::mpl::vector<ids::a0, ids::a3>, boost::mpl::same_as<get_first<mpl_::arg<1> > > >’
/usr/include/boost/mpl/find.hpp:28:8:   required from ‘struct boost::mpl::find<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/aux_/contains_impl.hpp:33:54:   required from ‘struct boost::mpl::contains_impl<boost::mpl::aux::vector_tag>::apply<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/contains.hpp:30:8:   required from ‘struct boost::mpl::contains<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
tests.cpp:70:16:   required from here
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:62:63: error: no type named ‘type’ in ‘struct boost::mpl::apply2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:65:78: error: no type named ‘type’ in ‘struct boost::mpl::apply2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
tests.cpp: In instantiation of ‘struct get_first<mpl_::arg<1> >’:
tests.cpp:70:16:   required from here
tests.cpp:37:34: error: no type named ‘first_type’ in ‘struct mpl_::arg<1>’

From the very first line of the error messages there is something completely unexpected for me tests.cpp: In instantiation of ‘struct get_first<ids::a0>’. This should not happen because get_first should only be instantiated using elements of map_type, i.e. fusion::pair. I really don't understand why this is happening.

As I said, it works perfectly with boost 1.40, and it makes a lot of sense for me as it is written now, so I really don't see where the error is. My only guess is that something might have changed in the newer versions of fusion or mpl that is causing this. Actually I checked the change logs of Boost.Fusion and Boost and something related to fusion views have been modified/added. Maybe a bug? or, Am I missing something? why it does not work with the newer versions of boost that I tried?

thanks in advance!


回答1:


Using:

typedef boost::fusion::result_of::filter_if<
            map_type
            , 
            boost::mpl::lambda<
                boost::mpl::contains<
                    vec_ids_type
                    , 
                    get_first<
                        boost::mpl::_1
                    >
                >
            >::type
        >::type view_type;

Seems to make it work as you can see here. Currently LiveWorkspace uses boost 1.53.0.



来源:https://stackoverflow.com/questions/15797525/boost-fusion-mpl-issues-after-upgrade-to-a-newer-version

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!