RiaD
RiaD

Reputation: 47620

Move semantic and temporary implicit this

Is it possible to create method that will work differently when object *this is actually a temporary?

For example:

#include <iostream>

struct BigObj{
    void changeFast() {}
};

class A {
    BigObj obj;
public:
    A(){}
    A(const A& a) {
        obj = a.obj;
        std::cout << "copy\n";
    }
    A(A&& a) {
        obj = std::move(a.obj);
        std::cout << "move\n";
    }
    A changed() {
        A ret = *this; //(1)
        ret.obj.changeFast();
        return ret;
    }
};

int main(){
    A a;
    A b = std::move(a).changed();
    (void)b;
    return 0;
}

In line (1) we have copy but it's not really needed. But we can't always move here because sometimes method called on not-temporary. What should one do to avoid copy here?

If it was not method but just function one may write to similar functions:

A changed(const A& a){
}

A changed(A&& a){
}

Upvotes: 3

Views: 59

Answers (2)

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153840

You can overload functions on the r-valueness of *this. For example:

class A
{
public:
    // ... 
    A changed() const&; // called for l-values
    A changed() &&;     // called for r-values
};

You cannot overload a version without reference qualification with one having reference qualifcations, though. See 13.1 [over.load] paragraph 2, third bullet:

Member function declarations with the same name and the same parameter-type-list as well as member function template declarations with the same name, the same parameter-type-list, and the same template parameter lists cannot be overloaded if any of them, but not all, have a ref-qualifier (8.3.5).

Upvotes: 4

Kerrek SB
Kerrek SB

Reputation: 477040

Yes, you need to declare A changed() &&;. This overload will be available when the instance is an rvalue.

struct A
{ 
    void foo() &  { }
    void foo() && { }
};

int main()
{
    A x;
    x.foo();             // picks first overload
    std::move(x).foo();  // picks second overload
    A().foo();           // "typical" use case for second overload
}

This new language feature may not be supported by all compilers yet.

Upvotes: 3

Related Questions