Boost logo

Boost :

From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-11-20 08:17:55

David A. Greene wrote:
> I'm starting to explore mpl a bit and I ran into a roadblock.
> If I have a template that takes an argument that can be
> a sequence (e.g. mpl::vector) or a regular old type, is
> there any way, short of specialization, to determine whether
> the parameter is a sequence?

"is_sequence<T>::value", please expect it to appear in the CVS in a day or
two :).

> I'd like to avoid specializing the template based on mpl guts
> that may change. Alternatively, is there any way to manipulate
> the parameter to guarantee that it is converted to a sequence (of
> one element) if it is not a sequence?

Given 'is_sequence', it will be as simple as this:

    template< typename T >
    struct as_sequence
        : if_< is_sequence<T>, T, single_view<T> >

> Here's a second question. Suppose I have a "chain" of types
> such that each type contains as a member the next type in the
> chain. For example:
> struct third;
> struct second;
> struct first;
> struct first {
> typedef second type;
> };
> struct second {
> typedef third type;
> };
> struct third {
> typedef boost::mpl::void_ type;
> };
> If I want to use this kind of intrusive sequence with mpl,
> how would I go about defining begin<> and end<>? The headers
> use something called begin_traits and end_traits but they
> assume that the type passed is an mpl-style sequence that
> has begin and end members defined.

Actually, as the comments say, that is a default implementation. You can
override it in two ways - (partially) specialize the primary 'begin/end'
templates, or specialize 'begin_trait/end_trait' on a sequence tag to
implement something like this:

    struct my_sequence_tag;

    struct first {
        typedef my_sequence_tag;
        typedef second type;

    struct second {
        typedef my_sequence_tag;
        typedef third type;

    struct third {
        typedef my_sequence_tag;
        typedef boost::mpl::void_ type;

    struct begin_traits<my_sequence_tag>
        template< typename Sequence > struct algorithm
            typedef my_iterator<Sequence> type;

    template< typename Tag >
    struct end_traits
        template< typename Sequence > struct algorithm
            typedef my_iterator<void_> type;

Would it cover your needs?

> I thought about designing some kind of wrapper that could
> be used in specialization:
> template<typename Node>
> struct intrusive_list {
> typedef Node::type type;
> };
> Then I could partially specialize begin<>/end<> on
> intrusive_list. Is this a reasonable approach?

It is, at least from the technical standpoint - 'begin/end' /
'begin_trait/end_trait' templates were intended to be specialized; I would
need some user-level examples of intended usage for the whole thing to be
able to judge if there is a better way here.

> Here's one final puzzle: I have two type vectors that
> I'd like to merge into one. The trick is that I want
> to eliminate all duplicates. Since types cannot be
> ordered (how does one define a less-than operation?)

This one might be solvable (a challenge! :), but I don't have a solution
right now.

> it seems that type vectors cannot be easily sorted.
> Thus to do a concat/copy while eliminating duplicates
> would seem to be a very expensive task (search for
> each candidate in the built-up list before adding it).
> Any ideas here? I know I'm missing something important.

Well, it's not an easy one :). For now, I would suggest you to go with the
algorithm you've outlined above and see if the performance is a showstopper.
I am sure we'll figure something out, it just needs some amount of thought
that I am not able to dedicate to it at the moment. Thoughts are welcome!

> Great work by all on mpl -- I'm enjoying the exploration!

Thank you!


Boost list run by bdawes at, gregod at, cpdaniel at, john at