Re: Metaprogramming woes
"White Wolf"
Hi Dave,
Hi Atilla, In future please post your questions to the boost-users list so that the whole community can benefit.
I am trying to do something very simple, but I am going bananas. I have types, each of them has a "static member" (enum label) called nr_. I make a boost::mpl::list of them, and I would like to add them all together. But if I write _2::nr_, it says there is no nr_.
Well, the author of _2 can't anticipate all the nested values you
might be using. _2 is not magic; it's just a type.
// !! untested code !!
#include
::type sum;
// sum::value contains the value you're interested in.
I fugured it wants a type. So I have made a typedef inside called type, which has a boost::mpl::integer_c
in it. But it does not work, it gives me back the type of the last list element as a result. I try to use mpl::accumulate.
Yes, that's a synonym for fold if you have a version of the MPL that includes accumulate.
Finally I guess I will have to use transform in some way, because I need a list which has an mpl::pair (if there is one)
http://www.boost.org/libs/mpl/doc/refmanual/pair.html
of the original type and the sum of all nr_'s before it.
Seems like it's still a job for fold. In this case I'd use mpl::vector because lists can only be push_front-ed and you probably don't want to end up with your elements in "reverse" order. typedef mpl::fold< some_list , mpl::pair< // initial state mpl::vector0 // initial sequence , mpl::size_t<0> // initial sum > , mpl::pair< // the state at each step is a pair containing mpl::push_front< // added to the front of... mpl::first<_1> // the sequence from the previous step , mpl::pair< // a new element, a pair containing _2 // the original type , mpl::plus< // and the sum of mpl::second<_1> // the sum from previous step , get_nr_<_2> // the ::nr_ of the original type > > > , mpl::plus< // and the sum of mpl::second<_1> // the sum from previous step , get_nr_<_2> // the ::nr_ of the original type > >
::type pair_seq_sum;
typedef pair_seq_sum::first new_sequence;
So this is pretty verbose using lambdas because the sum is repeated,
among other things. You might do better to build a custom metafunction
that gets you the new state:
template
Can you help me? I have something like this:
struct T1 { enum x { label1, label2, nr_; }; };
// Same for T2, possibly less or more labels etc.
And I would like to end up with a type which looks like this:
struct something { int get(T1::x n) { return arr_[n]; } int get(T2::x n) { return arr_[n+2];
Where does n+2 come from?
} // etc. private: int arr_[sum_of_all_nr_]; };
?? that doesn't look anything like what you just described.
Sheesh. The above is still a job for fold.
I suggest you start with a base type:
template <class Derived>
struct base
{
enum { sum = 0 };
void get(); // never used.
};
then build layers:
template
David Abrahams
So this is pretty verbose using lambdas because the sum is repeated, among other things. You might do better to build a custom metafunction that gets you the new state:
template
struct next_state { typedef typename PrevState::first prev_sequence; typedef typename PrevState::second prev_sum; typedef mpl::size_t<(prev_sum::value + Element::nr_)> new_sum; typedef typename mpl::push_back< prev_sequence , mpl::pair >::type new_sequence; typedef mpl::pair type; }; typedef mpl::fold< some_list, mpl::fold<_,_> >::type pair_seq_sum;
typedef pair_seq_sum::first new_sequence;
Heh, this probably would've been easier using zip_view. Oh, well, I'm outta time for this one right now. Again, sorry. -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (1)
-
David Abrahams