Boost logo

Boost :

From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-10-08 03:58:31


Yitzhak Sapir wrote:
> > std::list<int> primes(
> > make_init_iterator<int, mpl::ct_list<2,3,5,7,11> >(),
> > make_init_iterator<int>());
> >
> > For exact syntax consult MPL list specification.
> >
>
> I consulted, and it seems it should be list_c?

Yep.

> Anyhow, there is unfortunately no way to easily generate an array
> of ints from 2, 3, 5, 7, 11. And I will use this point to ask/learn of
> mpl in an area in which I am curious. And that is, I can't seem to
> find how I would make any class type S such that
> int S<mpl::ct_list<2,3,5,7,11> >::value[] = {2, 3, 5, 7, 11};

There is no known way to generate array initialization list using templates;
it's one of the tasks where preprocessor metaprogramming is a more
appropriate tool.

> It would be nice if it could be done. Without it, the
> iterator that feeds into the list constructor has to travel upon the
> initialization list each time * is called.

That's because STL iterator model is not flexible enough to cover some types
of iteration effectively. In particular, in order to iterate "natively" over
tuples and compile-time lists iterator increment/decrement operations should
be allowed to change its type. Support for this requirement makes even
simple algorithms highly recursive and quite complicated, though.

Of course, you can always turn a type-mutating iterator into ordinary one by
applying handle-body idiom, but then you lose in efficiency - something that
tuple or compile-time list of values most probably had been chosen for in
the first place.

> (The iterator that feeds into the list is a run time construct,
> that has to convert the mpl compile-time construct into a run
> time function).

> In mpl, I understand this would generate
> something that if written in code would look like:
>
> int operator*()
> {
> switch (current_index) {
> case 0: return 2; // mpl::at_c<0, Sequence>::value;
> case 1: return 3; //etc.
> }
> throw out_of_range();
> }
>
> The traversal through the switch is usually a linear operation. This
> means that construction of the list requires traversal through n items
> each of which does traversal through n items, or a quadratic
> operation.

The above is definitely ugly. Three ways to solve it:

1) rewrite STL in accordance with a more general iterator model (contact me
privately if you are up to it ;)
2) implement a polymorphic wrapper for type-mutating iterators
3) give up the initialization syntax and re-write the original snippet like
this:

    std::vector<int> v;
    typedef mpl::list_c<int,2,3,5,7,11> primes;
    mpl::for_each< primes >(
          boost::bind(&std::vector<int>::push_back, &v, _1)
        );

The third way is available out-of-box with MPL & Boost.Bind.

[...]

> I still think that the way I posted should be available. For
> example, for inserting values into a map which requires feeding in an
> initialization list of pairs. Is there a way to specify a pair in mpl?

mpl::pair<T1,T2>

> The integral constant case is probably a frequently used case but it's
> not the only case.

Definitely. But our inability to deal with it in a satisfactory way because
of either library or language constraints kind of sucks ;).

Aleksey


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