5
votes

The following code fails with gcc 4.8.0 (mingw-w64) with -O2 -std=c++11 -frtti -fexceptions -mthreads

#include <string>

class Param
{
public:
    Param() : data(new std::string) { }

    Param(const std::string & other) : data(new std::string(other)) { }

    Param(const Param & other) : data(new std::string(*other.data)) { }

    Param & operator=(const Param & other) {
        *data = *other.data; return *this;
    }

    ~Param() {
        delete data;
    }

    Param & operator=(Param &&) = delete;


private:
    std::string * data;
};


int main()
{
    Param param;
    param = Param("hop");


    return 0;
}

With the error : error: use of deleted function 'Param& Param::operator=(Param&&)' On the line :

param = Param("hop");

And compiles well if I remove the move assignment delete line.

There should be no default move assignment operator since there are user defined copy constructors, user defined copy assignment, and destructors, so deleting it should not affect the compilation, why is it failing? And why is the allocation simply not using a copy assignment?

1
I'm not going to comment on your problem, just that you're using your constructor wrong. You should use the initializer list of your constructor, like so: Param():data(new std::string){} because otherwise you're doing some weird initialization then assignment. - user2030052
OK, I did some change to the code to fix some mistakes & answer to comments, but this does not change the result - galinette
= delete means "calling this function is an error", not "remove this function from the overload set." - Casey
@Casey: I keep forgetting that, and I hate it. It should remove it from the overload set, and use the copy assignment instead. - Mooing Duck
@MooingDuck : you are right in your editing of the question that this is an allocation and not a construction. I am still wrongly assuming that the compiler will optimize this to a simple constructor as if I wrote Param param("hop"); - galinette

1 Answers

6
votes

The function you deleted is exactly the assignment operator you try to use in main. By explicitly defining it as deleted you declare it and at the same time say using it is an error. So when you try to assign from an rvalue (Param("hop")), the compiler first looks whether a move assignment operator was declared. Since it was and is the best match, it tries to use it, just to find that it was deleted. Thus the error.

Here's another example of this mechanism which uses no special functions:

class X
{
  void f(int) {}
  void f(short) = delete;
};

int main()
{
  X x;
  short s;
  x.f(s);  // error: f(short) is deleted.
}

Removing the deleted f(short) will cause the compiler to select the non-deleted f(int) and thus compile without error.