On Tue, Mar 13, 2012 at 11:13 PM, Peter Nyssen <peter@dynsws.com> wrote:
Hi all,

I'm trying to understand how to use mpl::fold to transform a vector like this:
vector<
    pair<tag1, A>
    pair<tag2, B>
    pair<tag1, C>
>

into the following:
pair<
    vector<A,C>
    vector<B>
>

Following test program fails to compile and I don't understand why.
If you could explain me what I'm missing here, you will gain my eternal respect.

Kind regards,
Peter


//--------------------------------------------

#include <boost/mpl/if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/vector.hpp>

namespace mpl = boost::mpl;

struct tag1 {};
struct tag2 {};

template <typename T>
struct is_tag1 : boost::false_type {};

template <>
struct is_tag1<tag1> : boost::true_type {};

int main()
{
    typedef mpl::vector<
        mpl::pair<tag1, mpl::int_<1> >,
        mpl::pair<tag2, mpl::int_<2> >,
        mpl::pair<tag1, mpl::int_<3> >
    > initial_vector;

    typedef typename mpl::fold<
        initial_vector,
        mpl::pair<mpl::vector<>, mpl::vector<> >,
        mpl::if_<
            is_tag1<mpl::first<mpl::_2>::type >,
            mpl::push_back<
                mpl::first<mpl::_1>::type,
                mpl::second<mpl::_2>::type
            >,
            mpl::push_back<
                mpl::second<mpl::_1>::type,
                mpl::second<mpl::_2>::type
            >
        >
    >::type sorted_pair;

Try removing all the ::type's in the fold operation and rely on lazy evaluation. mpl:first< mpl::_1 >::type is equivalent to mpl::_1::first, which of course doesn't exist and isn't what you want; but mpl::first< mpl::_1 > is a placeholder expression equivalent to the mapping ( T0, ... ) -> T0::first, which looks like what you want.


    return 0;
}

//--------------------------------------------


 $ g++ -Wall -I ../boost/ -o test test.cpp
In file included from test.cpp:5:0:
../boost/boost/mpl/pair.hpp: In instantiation of ‘boost::mpl::first<mpl_::arg<2> >’:
test.cpp:32:40:   instantiated from here
../boost/boost/mpl/pair.hpp:43:31: fout: no type named ‘first’ in ‘struct mpl_::arg<2>’

:: cough ::
 
test.cpp: In functie ‘int main()’:
test.cpp:32:47: fout: template argument 1 is invalid
In file included from test.cpp:5:0:
../boost/boost/mpl/pair.hpp: At global scope:
../boost/boost/mpl/pair.hpp: In instantiation of ‘boost::mpl::first<mpl_::arg<1> >’:
test.cpp:34:36:   instantiated from here
../boost/boost/mpl/pair.hpp:43:31: fout: no type named ‘first’ in ‘struct mpl_::arg<1>’
../boost/boost/mpl/pair.hpp: In instantiation of ‘boost::mpl::second<mpl_::arg<2> >’:
test.cpp:35:37:   instantiated from here
../boost/boost/mpl/pair.hpp:56:32: fout: no type named ‘second’ in ‘struct mpl_::arg<2>’
test.cpp: In functie ‘int main()’:
test.cpp:36:13: fout: template argument 1 is invalid
test.cpp:36:13: fout: template argument 2 is invalid
In file included from test.cpp:5:0:
../boost/boost/mpl/pair.hpp: At global scope:
../boost/boost/mpl/pair.hpp: In instantiation of ‘boost::mpl::second<mpl_::arg<1> >’:
test.cpp:38:37:   instantiated from here
../boost/boost/mpl/pair.hpp:56:32: fout: no type named ‘second’ in ‘struct mpl_::arg<1>’
test.cpp: In functie ‘int main()’:
test.cpp:40:13: fout: template argument 1 is invalid
test.cpp:40:13: fout: template argument 2 is invalid
test.cpp:41:9: fout: template argument 1 is invalid
test.cpp:41:9: fout: template argument 2 is invalid
test.cpp:41:9: fout: template argument 3 is invalid
test.cpp:42:5: fout: template argument 3 is invalid
test.cpp:42:24: fout: invalid type in declaration before ‘;’ token

See if that helps. (Too lazy to try it on my own.)

- Jeff