Boost logo

Boost :

Subject: Re: [boost] [non-instrusive move] interest in new library?
From: THOMAS JORDAN (tomjordan766_at_[hidden])
Date: 2013-01-11 06:36:49


Thomas Jordan wrote:

>Jeffrey Lee Hellrung, Jr. wrote
>> You didn't really expound on the implementation, but, if I had to guess,
>> you'd also require your types to be default constructible, and it would
>> perform suboptimally (worse than leaving the move call out) if the swap
>> member function was equivalent to std::swap. I think this might preclude
>> its use in generic contexts and limit its use to situations where you
>> *know* the type is std::vector-like. Let me know if I'm presuming
>> incorrectly :)
>>
>
>Yes, it certainly requires the types to be default constructible.
>
><snip>
>
>The alternative would be to have just the single, default, template move
>function:
>
>//pseudo-code
>move(T& left, T& right)
>
>plus a pair of template functions to move to and from temporaries
>respectively:
>
>T move(T& x)
>void move(const T& from, T& to)
>
>then have optimised move functions defined on a per-type basis, e.g.,
>
>MyClass
>{
> void swap(MyClass& other)
> {
> //efficient swap member
> }
>
> friend void swap(MyClass& lhs, MyClass& rhs){}
>
> friend void move(MyClass& lhs, MyClass& rhs)
> {
> lhs.swap(rhs);
> }
>}
>
>as well as overloads defined for any cheap-to-swap library types
>interested in:
>
>void move(std::vector& lhs, std::vector& rhs){}
>void move(boost::function& lhs, boost::function& rhs){}
>etc.
>
>Although this is safer in that it should ensure optimality - and is
>actually where I started - it requires more boilerplate to be written,
>though there may be way(s) to automate the generation of the the
>user-type's move function. Also, with the library move functions
>implemented like this, you could still write algorithms like
>move()/move_backwards() (and helper functions
>such as iter_move() to move the values between two iterators) generically.

Also generic overloads of the move() function would be provided for built
in arrays and
e.g., boost::array

//pseudocode

void move(boost::array<T,N>& from, boost::array<T,N>& to){}

void move(T (& left)[N], T (& right)[N]){}
which would be implemented with a call to move(left[i], right[i]) for each
element,
in which case the elements would be swapped if a move overload has been
defined for the element type, copied otherwise, thereby preserving
optimality.
It would work for multi-dimensional (boost) arrays in a recursive fashion.

>So I guess the new question is, would this even smaller library be of
>any interest?
>Its use-cases would be the same as described in my original post, just
>to reiterate:
>
>//use-case: returning a argument directly from a function
>
>std::string foo(std::string s)
>{
> //e.g., append something to s
> //...
>
> //compiler can perform rvo (compiler would likely not
> //perform nrvo if just used 'return s;')
>
> return move(s);
>}
>
>
>//use-case: moving a value to a function/ctor, when the value is not
>//required by the calling code after the function/ctor call
>
>std::string s("hello");
>void bar(std::string s){...}
>
>bar(s); //copy
>bar(move(s)); //move
>//s has now been moved out of
>
>
>//use-case: moving a value into place
>void MyClass::MyClass(std::string s)
>{
> //move value from s into default constructed member s_
> move(s, s_);
>}
>
>Note that the combination of both moving a value to a function/ctor and
>then moving it into place, e.g.,
>
>std::string lv;
>//...
>
>MyClass mc(move(lv));
>
>
>effectively results in a zero-copy invocation, with just a small number of
>fixed size swap, default ctor and shallow dtor calls, so this is pretty
>efficient.

>//use-case: moving a temporary into an lvalue
>std:: string lv;
>move(foo(), lv);
>
>
>> - Jeff
>Tom

Tom


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