Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Backporting std::move code

66 views
Skip to first unread message

bitrex

unread,
Aug 14, 2016, 11:11:34 AM8/14/16
to
I'm working on rewriting a piece of code that was written to the C++11
standard for a device whose STL seems to only be C++0x compliant. Is
there a standard way to "backport" code using C++11's std::move operation?

Here is the context (where SignalSource is a class and I believe
SampleType is some fashion of integer type):

SignalSource operator+(SignalSource&& lhs, SampleType x)
{
lhs += x;
return std::move(lhs);
}

SignalSource operator+(SampleType x, SignalSource&& rhs)
{
rhs += x;
return std::move(rhs);
}

My understanding is that std::move is to avoid making unnecessary copies
of objects on the stack when the source/destination is going to be
destroyed anyway, so I didn't know if there was some "canonical" way to
backport this.

Öö Tiib

unread,
Aug 14, 2016, 5:27:38 PM8/14/16
to
On Sunday, 14 August 2016 18:11:34 UTC+3, bitrex wrote:
> I'm working on rewriting a piece of code that was written to the C++11
> standard for a device whose STL seems to only be C++0x compliant. Is
> there a standard way to "backport" code using C++11's std::move operation?
>
> Here is the context (where SignalSource is a class and I believe
> SampleType is some fashion of integer type):
>
> SignalSource operator+(SignalSource&& lhs, SampleType x)
> {
> lhs += x;
> return std::move(lhs);
> }
>
> SignalSource operator+(SampleType x, SignalSource&& rhs)
> {
> rhs += x;
> return std::move(rhs);
> }

Do not forget that the move of C++11 is *only* performance optimization
of reusing value that is going to be discarded. It is simple to get rid
of that optimization:

SignalSource operator+(SignalSource const& lhs, SampleType x)
{
SignalSource ret(lhs);
ret += x;
return ret;
}

SignalSource operator+(SampleType x, SignalSource const& rhs)
{
SignalSource ret(rhs);
ret += x;
return ret;
}

>
> My understanding is that std::move is to avoid making unnecessary copies
> of objects on the stack when the source/destination is going to be
> destroyed anyway, so I didn't know if there was some "canonical" way to
> backport this.

Canonical is to assume that copy or move does not matter and copy is fine.
On majority of cases it actually is correct assumption.

C++03 did have smart pointer named 'std::auto_ptr' that did always move
instead of copy. That was nice but dangerous to use because first less
experienced maintainer that touched the code likely screwed it up.

Some code used members called 'swap' for achieving move-like effect to
efficiency where needed. There were no rvalue-references (from what it
is safe to move or to swap) so if someone wanted to move from reference
to temporary then he had to cast constness away.


Alf P. Steinbach

unread,
Aug 14, 2016, 5:58:34 PM8/14/16
to
On 14.08.2016 17:11, bitrex wrote:
> I'm working on rewriting a piece of code that was written to the C++11
> standard for a device whose STL seems to only be C++0x compliant. Is
> there a standard way to "backport" code using C++11's std::move operation?
>
> Here is the context (where SignalSource is a class and I believe
> SampleType is some fashion of integer type):
>
> SignalSource operator+(SignalSource&& lhs, SampleType x)
> {
> lhs += x;
> return std::move(lhs);
> }
>
> SignalSource operator+(SampleType x, SignalSource&& rhs)
> {
> rhs += x;
> return std::move(rhs);
> }

I think this is probably not your actual code. Your actual code is
probably templated on SignalSource, in which case the && is a universal
reference. In the non-templated code given above, && is an rvalue
reference, which would only permit rvalue expression as actual argument.

Anyway, you can either

• remove the move optimization (just copy things) or

• implement /explicit/ move operations.


> My understanding is that std::move is to avoid making unnecessary copies
> of objects on the stack when the source/destination is going to be
> destroyed anyway, so I didn't know if there was some "canonical" way to
> backport this.

Nope, but if, after measuring the simple copy solution, you find that
moving is really required, then instead of implementing your own
explicit C++03 move operations you could look up Andrei Alexandrescu's
Mojo article in DDJ.


Cheers & hth.,

- Alf

bitrex

unread,
Aug 14, 2016, 6:33:38 PM8/14/16
to
Nice, thank you for your insight. I've started using C++11 a bit on the
desktop and the unique_ptr smart pointer syntax does make life a lot
easier.

Unfortunately this particular thing is for an embedded platform, so all
that cool automatic memory management stuff that assumes a system MMU is
out the door.

Öö Tiib

unread,
Aug 15, 2016, 9:28:12 AM8/15/16
to
On small embedded platforms such dynamic memory management for what we
need smart pointers is typically avoided whatsoever. Fixed amount of external
connections, fixed data, fixed queues, arrays and ring buffers. Also move does
not give much advantages there.

Moves (and whatever other ways to cache and to reuse) do give advantages on
bigger systems with dynamic amount of threads, dynamic external connections,
multi-media, unpredictable amounts of different kinds of data etc.

bitrex

unread,
Aug 15, 2016, 2:57:28 PM8/15/16
to
Yep. I try to instantiate all the objects that are required for the life
of the program immediately on startup, and for whatever's left that
needs to be dynamically allocated within a class, there's a fixed
"buffer area" of the required size, and *const members that are used
along with placement new.

SG

unread,
Aug 24, 2016, 7:16:47 AM8/24/16
to
On Sunday, August 14, 2016 at 11:27:38 PM UTC+2, Öö Tiib wrote:
> On Sunday, 14 August 2016 18:11:34 UTC+3, bitrex wrote:
> > I'm working on rewriting a piece of code that was written to the C++11
> > standard for a device whose STL seems to only be C++0x compliant. Is
> > there a standard way to "backport" code using C++11's std::move operation?
> >
> > Here is the context (where SignalSource is a class and I believe
> > SampleType is some fashion of integer type):
> >
> > SignalSource operator+(SignalSource&& lhs, SampleType x)
> > {
> > lhs += x;
> > return std::move(lhs);
> > }
> >
> > SignalSource operator+(SampleType x, SignalSource&& rhs)
> > {
> > rhs += x;
> > return std::move(rhs);
> > }
>
> Do not forget that the move of C++11 is *only* performance optimization
> of reusing value that is going to be discarded. It is simple to get rid
> of that optimization:
>
> SignalSource operator+(SignalSource const& lhs, SampleType x)
> {
> SignalSource ret(lhs);
> ret += x;
> return ret;
> }
>
> SignalSource operator+(SampleType x, SignalSource const& rhs)
> {
> SignalSource ret(rhs);
> ret += x;
> return ret;
> }

There is still some "swaptimization" possible. In your version you are
forcing copy constructions with

SignalSource ret(lhs);

But it's usually better to have the compiler worry about how to create
such a "copy" by taking the parameter by value because this allows the
compiler to do some copy elisions in some cases:

SignalSource operator+(SignalSource temp, SamplesType x)
{
// intentional call-by-value here ^

SignalSource ret; // cheap constructor
ret.swap(temp); // cheap swap

ret += x;
return ret; // NRVO applicable
}

Now you might wonder why I created yet another local object. I could
have worked on and returned temp directly. This has to do with the
named return value optimization (NRVO). Compilers don't do that kind
of optimization if the source is a function parameter ... because
nobody knows how to implement that. It only works for function-local
things that are NOT parameters.

I would argue that this version -- provided that SignalSource has such
a cheap constructor and swap function -- is preferable to your version
in all cases because it's never worse but sometimes saves unnecessary
copies. These tricks were quite popular in the pre-C++11 time. I
recall at least two people blogging about it. Dave Abrahams had a
series of articles on cpp-next.com which is not available anymore,
unfortunately. Stephan T. Lavavej coined the term "swaptimization"
IIRC. Though, it's been a while and my memory is fuzzy.

Cheers!
SG
0 new messages