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