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;
    };


    template<>
    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!

HTH,
Aleksey
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to