Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rvalues with copy operator

Tags:

c++

c++11

Consider this simple class

class Foo
{
    public:
    Foo() = default;
    Foo(const Foo &) = default;
    Foo & operator=(const Foo & rhs)
    {
        return *this;
    }
    Foo & operator=(Foo && rhs) = delete; 
};

Foo getFoo()
{
    Foo f;
    return f;
}

int main()
{
    Foo f;
    Foo & rf = f;
    rf = getFoo();    // Use of deleted move assignment.
    return 0;   
}

When I compile the example above I get error: use of deleted function 'Foo& Foo::operator=(Foo&&)'

From the Copy Assignment:

If only the copy assignment is provided, all argument categories select it (as long as it takes its argument by value or as reference to const, since rvalues can bind to const references), which makes copy assignment the fallback for move assignment, when move is unavailable.

Why doesn't the compiler fallback to copy assignment when const lvalue reference can bind to rvalue and const Foo & f = getFoo(); works.

Compiler - gcc 4.7.2.

like image 384
Peter Silon Avatar asked Jul 29 '16 08:07

Peter Silon


People also ask

What is R value Referene in C++11?

In C++11, however, the rvalue reference lets us bind a mutable reference to an rvalue, but not an lvalue. In other words, rvalue references are perfect for detecting whether a value is a temporary object or not.

What is the copy and swap idiom?

Copy-and-Swap Idiom in C++ But when overloading the assignment operator, it can become quite difficult to implement. The copy and swap idiom is a solution for the same. This idiom uses the copy-constructor to build a local copy of the data. It then swaps the old data with the new data using the swap function.

How do you use rvalue reference in C++?

If the function argument is an rvalue, the compiler deduces the argument to be an rvalue reference. For example, assume you pass an rvalue reference to an object of type X to a template function that takes type T&& as its parameter. Template argument deduction deduces T to be X , so the parameter has type X&& .

What is a copy assignment operator?

A copy assignment operator of class T is a non-template non-static member function with the name operator= that takes exactly one parameter of type T, T&, const T&, volatile T&, or const volatile T&. For a type to be CopyAssignable, it must have a public copy assignment operator.


1 Answers

There is no fallback, the concept is called overload resolution.

The compiler performs the overload resolution and makes the decision before it checks whether the method is deleted or not. The compiler decides that the move constructor is the best choice, then it determines that this method has been deleted, hence the error.

Note 1: delete does not literally delete the method. If delete is used, the method is defined as deleted, but it still can be found by the overload resolution.

From the cppreference.com documentation (emphasis mine):

... overload resolution takes place first, and the program is only ill-formed if the deleted function was selected.

In your example, the move constructor is available (from the overload resolution point of view). However, it is defined as deleted.

Note 2: If you don't want your class to have a move constructor, simply do not define it. The compiler will not generate a move constructor if you have declared one of the following: copy constructor, copy assignment operator, move assignment operator, destructor.

like image 166
sergej Avatar answered Oct 11 '22 22:10

sergej