|
Boost : |
From: David Abrahams (dave_at_[hidden])
Date: 2003-01-23 11:19:58
Douglas Paul Gregor <gregod_at_[hidden]> writes:
> On Thu, 23 Jan 2003, David Abrahams wrote:
>
>> Douglas Paul Gregor <gregod_at_[hidden]> writes:
>>
>> > Why don't we have
>> >
>> > mpl::list<int, float, double, std::string> list_of_types;
>> > for_each(list_of_types.begin(), list_of_types.end(), f);
>> >
>> > ?
>> >
>> > Then an unqualified for_each call can handle type sequences, heterogeneous
>> > containers (e.g., tuple), and run-time sequences (e.g., vector). It's been
>> > done before, elsewhere, so why don't we do it in MPL?
>>
>> It's clever, but I'm not sure what problem it's solving.
>
> I mentioned this before and cited the paper "Static Data
> Structures: Reconciling Template Metaprogramming and Generic Programming":
> http://aspn.activestate.com/ASPN/Mail/Message/1304415
>
> The title says it all: we have generic programming and template
> metaprogramming, and they complement each other nicely, but at the barrier
> between them I feel that we have a kludge. MPL and STL are built on the
> same abstractions, with similar naming schemes and similar style, so why
> is it that at the bridge between the two we have something that looks like
> neither? I think the for_each syntax I'm referring to is a clean bridge
> between the two, because it (logically, if not in code) maps the syntax of
> STL iterators to the syntax of MPL iterators in standard algorithm calls.
> The paper I referred to gave the most compelling argument for having
> precisely the same syntax at the bridge: you can test with the run-time
> version (short compile times) and release with the compile-time version
> (short execution times): they needed only to switch the object from
> std::vector to a compile-time vector, wait for KAI C++ to grind away for
> 24 hours, and they got 171 times the performance.
OK, point taken. I think it's worth examining.
>> AFAICT it
>> doesn't solve the problem that Andrei was pointing at.
>
> You mean the front/pop_front issue?
No, I mean the complexity-of-expression issue.
>> It also has at
>> least one problem: it is intrusive on sequence types, requiring them
>> to have begin()/end() member functions. If this was the only way to
>> do it, it would break interoperability with 3rd-party type sequences.
>>
>> -Dave
>
> That's easy to fix---I was just trying to keep the example small. A few
> extra abstractions would be needed:
>
> namespace mpl {
> // Special type that for_each can pick up on
> template<typename Iterator>
> struct iterator
> {
> typedef Iterator type;
> };
>
> // Stores an MPL sequence defined by an iterator range
> template<typename Begin, typename End>
> struct sequence
> {
> iterator<Begin> begin() const { return iterator<Begin>(); }
> iterator<End> end() const { return iterator<End>(); }
> };
>
> template<typename Begin, typename End, typename F>
> F for_each(iterator<Begin> first, iterator<End> last, F f)
> {
> // ...
> }
> }
>
> Just stick your third-party iterators into sequence<> and you're all set;
> I'd expect that mpl::list, mpl::vector, etc. would just derive from
> mpl::sequence to reduce the amount of typing in the common case.
Maybe it would be better to define namespace-scope begin(), end(),
et. al which can operate on STL and MPL sequences.
-- David Abrahams dave_at_[hidden] * http://www.boost-consulting.com Boost support, enhancements, training, and commercial distribution
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk