Boost logo

Boost :

Subject: [boost] [mpl] cross product and gcc specific compiler error
From: Josh Quigley (0zeroth_at_[hidden])
Date: 2012-05-10 04:39:10


Hi,

A question from the grossly uninformed: I grabbed an mpl cross product
implementation (product_view) of this mailing list. It works fine in
MSVC but fails in gcc:

    typedef boost::mpl::vector<float, double, long double> DecimalTypes;
    typedef boost::mpl::vector<int, unsigned int, long, unsigned long,
long long, unsigned long long> IntegralTypes;

    typedef product_view<boost::mpl::vector<DecimalTypes,
IntegralTypes> > EachDecimalWithEachIntegralT;
    BOOST_AUTO_TEST_CASE_TEMPLATE(MyTest, DecimalIntegralT,
EachDecimalWithEachIntegralT)
    {
        {
            typename DecimalIntegralT::item1 r(1234567); // Fails on
gcc: no type named ‘item0’ in ‘struct boost::mpl::v_item<long long
unsigned int, boost::mpl::v_item<ext::decimal::decimal128,
            boost::mpl::vector0<mpl_::na>, 0>, 0>
            typename DecimalIntegralT::item0 d(r);

            BOOST_CHECK_EQUAL(static_cast<long long>(d), r);
        }
}

A complete listing is below. The thing that has me really stumped is
the type exsits in MSVC, so I'm at a bit of loss of how to proceed
debugging.

//
// LISTING
//

#include <boost/mpl/vector.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/type_traits/is_same.hpp>

#include <boost/function.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/test/unit_test.hpp>

namespace detail {

    using boost::mpl::at_c;
    using boost::mpl::at;
    using boost::mpl::vector3;
    using boost::mpl::true_;
    using boost::mpl::false_;
    using boost::mpl::if_;
    using boost::mpl::next;
    using boost::mpl::bool_;
    using boost::mpl::front_inserter;
    using boost::mpl::clear;
    using boost::mpl::forward_iterator_tag;
    using boost::mpl::reverse_copy;
    using boost::mpl::transform1;
    using boost::mpl::deref;
    using boost::mpl::_1;
    using boost::mpl::_2;
    using boost::mpl::int_;
    using boost::mpl::fold;
    using boost::mpl::or_;
    using boost::mpl::nested_begin_end_tag;

    template<typename S, typename O> struct state_with_overflow
    {
        typedef S state;
        typedef O overflow;
    };

    template<typename I3S> struct i3s_increment_inserter
    {
        template<typename I3, typename O> struct i3_
        {
            typedef I3 i3;
            typedef O overflow;
        };

        template<typename I3> struct incr_
        {
            typedef typename next< typename at_c< I3, 1 >::type
>::type next_;
            typedef bool_< boost::is_same< next_, typename
at_c<I3,2>::type >::value > overflow_;

            typedef i3_<
                vector3<
                typename at_c<I3,0>::type,
                typename if_< overflow_, typename at_c<I3,0>::type,
next_ >::type,
                typename at_c<I3,2>::type
>,
                overflow_
>
            type;
        };

        typedef front_inserter< typename clear<I3S>::type > base_;

        typedef state_with_overflow< typename base_::state,
true_ > state;

        struct operation
        {
            template<typename S, typename I3> struct apply
            {
                typedef typename if_<
                    typename S::overflow,
                    typename incr_<I3>::type,
                    i3_<I3,false_>
>::type next_;

                typedef state_with_overflow<
                    typename base_::operation::template apply<
typename S::state, typename next_::i3 >::type,
                    typename next_::overflow
>
                type;
            };
        };
    };

    template< typename SWO > struct product_iterator
    {
    private:

        typedef typename SWO::state I3S;

    public:
        typedef forward_iterator_tag category;

        typedef typename transform1<
            I3S, deref< at< _1, int_<1> > >
>::type type;

        typedef product_iterator<
            typename reverse_copy< I3S, i3s_increment_inserter<I3S> >::type
>
        next;
    };

    template<typename S> struct product_view
    {
    private:

        typedef typename transform1<
            S, vector3< boost::mpl::begin<_1>, boost::mpl::begin<_1>,
boost::mpl::end<_1> >
>::type
        begin_impl;

        typedef typename fold<
            S, false_,
            or_<
            _1, boost::is_same< boost::mpl::begin<_2>, boost::mpl::end<_2> >
            // empty<_2> refuses to compile on MSVC 7.1
>
>::type
        empty_result;

    public:

        typedef nested_begin_end_tag tag;

        typedef product_iterator< state_with_overflow< begin_impl,
empty_result > > begin;
        typedef product_iterator< state_with_overflow< begin_impl,
true_ > > end;
    };

}

using detail::product_view;

// typedef boost::mpl::vector<decimal32, decimal64, decimal128>
DecimalTypes; // Original
typedef boost::mpl::vector<float, double, long double> DecimalTypes;
  // for demonstration
typedef boost::mpl::vector<int, unsigned int, long, unsigned long,
long long, unsigned long long> IntegralTypes;

typedef product_view<boost::mpl::vector<DecimalTypes, IntegralTypes> >
EachDecimalWithEachIntegralT;
BOOST_AUTO_TEST_CASE_TEMPLATE(MyTest, DecimalIntegralT,
EachDecimalWithEachIntegralT)
{
    {
        typename DecimalIntegralT::item1 r(1234567); // Fails on
gcc: no type named ‘item0’ in ‘struct boost::mpl::v_item<long long
unsigned int, boost::mpl::v_item<ext::decimal::decimal128,
boost::mpl::vector0<mpl_::na>, 0>, 0>
        typename DecimalIntegralT::item0 d(r);

        BOOST_CHECK_EQUAL(static_cast<long long>(d), r);
    }
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk