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