Boost logo

Boost Users :

Subject: [Boost-users] [fusion] [mpl] binary mpl::transform on empty std::tuple
From: Nathan Ridge (zeratul976_at_[hidden])
Date: 2013-03-30 04:49:20


Hello,

Fusion provides adaptation code for treating an std::tuple
as a Fusion sequence, and adaptation code for treating
Fusion sequences as MPL sequences, but it seems that in
the case of a binary mpl::transform on an empty std::tuple,
the two do not work well together.

When trying to compile the following code:

#include <boost/mpl/transform.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/adapted/mpl.hpp>
#include <boost/fusion/mpl.hpp>

struct first
{
    template <typename T, typename U>
    struct apply
    {
        typedef T type;
    };
};

int main()
{
    typedef std::tuple<> fusion_sequence1_type;
    typedef std::tuple<> fusion_sequence2_type;
    typedef boost::mpl::transform<fusion_sequence1_type,
                                  fusion_sequence2_type,
                                  first,
                                  boost::mpl::back_inserter<boost::mpl::vector<>>
                                 >::type result_type;
}

I get the following errors:

In file included from test.cpp:4:
In file included from boost/fusion/adapted/std_tuple.hpp:13:
In file included from boost/fusion/adapted/std_tuple/detail/begin_impl.hpp:10:
boost/fusion/adapted/std_tuple/std_tuple_iterator.hpp:45:13: error: implicit instantiation of undefined template 'std::tuple_element<0, std::tuple<> >'
          : std::tuple_element<Iterator::index,
            ^
boost/fusion/iterator/value_of.hpp:34:28: note: in instantiation of template class 'boost::fusion::std_tuple_iterator<std::tuple<>, 0>::value_of<boost::fusion::std_tuple_iterator<std::tuple<>, 0> >' requested here
            struct apply : Iterator::template value_of<Iterator> {};
                           ^
boost/fusion/iterator/value_of.hpp:51:15: note: in instantiation of template class 'boost::fusion::extension::value_of_impl<boost::fusion::iterator_facade_tag>::apply<boost::fusion::std_tuple_iterator<std::tuple<>, 0> >' requested here
            : extension::value_of_impl<typename detail::tag_of<Iterator>::type>::
              ^
boost/fusion/iterator/mpl/fusion_iterator.hpp:46:45: note: in instantiation of template class 'boost::fusion::result_of::value_of<boost::fusion::std_tuple_iterator<std::tuple<>, 0> >' requested here
        typedef typename fusion::result_of::value_of<Iterator>::type type;
                                            ^
boost/mpl/iterator_category.hpp:27:22: note: in instantiation of template class 'boost::mpl::fusion_iterator<boost::fusion::std_tuple_iterator<std::tuple<>, 0> >' requested here
    typedef typename Iterator::category type;
                     ^
boost/mpl/pair_view.hpp:152:20: note: in instantiation of template class 'boost::mpl::iterator_category<boost::mpl::fusion_iterator<boost::fusion::std_tuple_iterator<std::tuple<>, 0> > >' requested here
          typename iterator_category<iter1_>::type
                   ^
boost/mpl/aux_/has_tag.hpp:20:1: note: (skipping 5 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_tag, tag, false)
^
boost/mpl/has_xxx.hpp:244:65: note: expanded from macro 'BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF'
            , boost::mpl::aux::type_wrapper<BOOST_MSVC_TYPENAME U::name>* = 0 \
                                                                ^
boost/mpl/transform.hpp:75:7: note: in instantiation of template class 'boost::mpl::fold<boost::mpl::pair_view<std::tuple<>, std::tuple<> >, boost::mpl::vector<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::bind2<boost::mpl::push_back<mpl_::na, mpl_::na>, mpl_::arg<1>, boost::mpl::bind2<first, boost::mpl::bind1<boost::mpl::first<mpl_::na>, mpl_::arg<2> >, boost::mpl::bind1<boost::mpl::second<mpl_::na>, mpl_::arg<2> > > > >' requested here
    : fold<
      ^
boost/mpl/transform.hpp:114:1: note: in instantiation of template class 'boost::mpl::aux::transform2_impl<std::tuple<>, std::tuple<>, first, boost::mpl::back_inserter<boost::mpl::vector<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> > >' requested here
BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(4, transform2)
^
boost/mpl/aux_/inserter_algorithm.hpp:44:7: note: expanded from macro 'BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF'
    : aux::name##_impl<BOOST_MPL_PP_PARAMS(arity, P)> \
      ^
boost/mpl/eval_if.hpp:38:22: note: in instantiation of template class 'boost::mpl::transform2<std::tuple<>, std::tuple<>, first, boost::mpl::back_inserter<boost::mpl::vector<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> > >' requested here
    typedef typename f_::type type;
                     ^
boost/mpl/transform.hpp:138:1: note: in instantiation of template class 'boost::mpl::eval_if<boost::mpl::or_<boost::mpl::is_na<first>, boost::mpl::is_lambda_expression<std::tuple<> >, boost::mpl::not_<boost::mpl::is_sequence<std::tuple<> > >, mpl_::bool_<false>, mpl_::bool_<false> >, boost::mpl::transform1<std::tuple<>, std::tuple<>, first>, boost::mpl::transform2<std::tuple<>, std::tuple<>, first, boost::mpl::back_inserter<boost::mpl::vector<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> > > >' requested here
AUX778076_TRANSFORM_DEF(transform)
^
boost/mpl/transform.hpp:125:22: note: expanded from macro 'AUX778076_TRANSFORM_DEF'
    typedef typename eval_if<                                           \
                     ^
test.cpp:21:25: note: in instantiation of template class 'boost::mpl::transform<std::tuple<>, std::tuple<>, first, boost::mpl::back_inserter<boost::mpl::vector<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> > >' requested here
    typedef boost::mpl::transform<fusion_sequence1_type,
                        ^
c++/4.8.0/tuple:672:12: note: template is declared here
    struct tuple_element;
           ^
1 error generated.

Seems like something is trying to call value_of on the begin iterator
of the tuple, which in the case of an empty tuple is a past-the-end
iterator.

If I use non-empty tuples instead:

    typedef std::tuple<int> fusion_sequence1_type;
    typedef std::tuple<int> fusion_sequence2_type;

It works fine. Unary mpl::transform works fine in either case.

Am I doing something wrong, or is this a bug?

Thanks,
Nate
                                               


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net