Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-12-17 17:28:58


David Abrahams wrote:
> > push_back(c, v) is a mutating operation on c. After it c has one
> > additional element pushed to its back, v.
>
> Okay, I see your point. There arer indeed some strange
> non-correspondences between MPL functions and their STL
> counterparts. For example, copy, which takes two input
> sequences and adds the elements of the first to the end of
> the second.

Agree, current 'mpl::copy' is strange. The intention was to allow 'copy' to
add elements to an output sequence, as well as to create a "fresh copy" of
them, and as I was sloppy at the time I wrote the function, instead of
defining compile-time Output Iterator concept and implementing inserters, I
decided to just go with the current interface:

    // (1) adds numbers [0..10] to a value_list<20,25,30,35>
    typedef mpl::value_list<20,25,30,35> numbers;
    typedef mpl::copy<
          mpl::value_range<0,10>
        , numbers // should support 'push_back'
>::type result;
    
    BOOST_MPL_ASSERT_IS_SAME(
          result
        , mpl::value_list<0, 1, 2, 3,.., 9, 10, 20, 25, 30, 35>
        );
 
    // should be something like
    //
    // typedef mpl::value_list<20,25,30,35> numbers;
    // typedef mpl::copy<
    // mpl::value_range<0,10>
    // , mpl::back_inserter<numbers>
    // >::type result;
    //
    // or (much more effective ;)
    //
    // typedef mpl::copy_backward<
    // mpl::value_range<0,10>
    // , mpl::front_inserter<numbers>
    // >::type result;

    // (2) duplicate a sequence
    typedef mpl::type_vector<char,short,int,long> types;
    typedef mpl::copy<
          types
        , mpl::type_list<> // should support 'push_back'
>::type result;
    
    BOOST_MPL_ASSERT_IS_SAME(
          result
        , mpl::type_list<char,short,int,long>
        );
 
    // should be something like
    //
    // typedef mpl::type_vector<char,short,int,long> types;
    // typedef mpl::copy<
    // types
    // , mpl::back_inserter< type_list<> >
    // >::type result;

> > append(a, b) is a pure function that returns the
> > concatenation of a and b.

'append' is a mutating operation on a container (as opposite to a sequence),
even if it returns (modified) copy of it; to understand that statement,
consider this hypothetical example from run-time world:

    std::vector<int> vector;
    std::list<int> list;

    template<typename T> void sink(T);

    // what is T in every sink<T>() specialization below?
    sink(append(vector, list)); // T == std::vector<int>
    sink(append(list, vector)); // T == std::list<int>
    sink(append(numbers_seq(0,10), list)); // T == ???

You cannot _append_ anything to an input sequence; you can _copy_ input
sequence elements into anything that satisfies the Output Iterator
requirements, and that "anything" can append your output container.

The same holds for compile-time world:

    typedef mpl::append<
          mpl::value_range<0,10>
        , mpl::value_vector<20,25,30,35>
>::type result; // typeof(result) == ???

    typedef mpl::copy<
          mpl::value_range<0,10>
        , mpl::back_inserter< mpl::value_vector<20,25,30,35> >
>::type result; // typeof(result) ==
mpl::value_vector<20,25,30,35,0,1,2,..,9>

'append<C,Sequence>' is operation on a compile-time container, while
'copy<InputSequence,OutputIterator>' is operation on compile-time
_sequence_. The first one requires its first argument to be a mutable
(extensible) container, and returns an appended copy of it; the second one
will work on anything that is an Input Sequence, and the result type (and,
to some extent, the semantics of the operation) is determined by a specific
instance of Output Iterator concept passed to it.

> > I might be wrong, though; it's been a while since I looked
> > at anything Lisp-related.
>
> In elisp, the docs say:
>
> Concatenate all the arguments and make the result a list.

So, it always returns a list?

> The result is a list whose elements are the elements of all
> the arguments.
> Each argument may be a list, vector or string.
> The last argument is not copied, just used as the tail of the
> new list.
>
> So I guess that would be a better name for what MPL calls copy.

I don't think so. Current 'copy' semantics is strange, but in any case
'append' is something completely different from what the 'mpl::copy'
algorithm has been intended to provide. I have nothing against adding the
'append' to the list of container operations such as 'push_back',
'push_front', 'insert', etc., though.

Aleksey


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