30

Is the following snipplet correct for un-defining all otherwise generated methods and constructors for a class?

struct Picture {

  // 'explicit': no accidental cast from string to Picture
  explicit Picture(const string &filename) { /* load image from file */ }

  // no accidental construction, i.e. temporaries and the like
  Picture() = delete;

  // no copy
  Picture(const Picture&) = delete;

  // no assign
  Picture& operator=(const Picture&) = delete;

  // no move
  Picture(Picture&&) = delete;

  // no move-assign
  Picture& operator=(Picture&&) = delete; // return type correct?
};

This deletes every default compiler implementation and only leaves the destructor, right? Without it the class would be (almost) unusable I guess, but I could delete it as well, correct?

Is the return type Picture& of the move-assign operator=(Picture&&) correct? Does it make a difference if I wrote Picture&& for the return type?

towi
  • 21,587
  • 28
  • 106
  • 187
  • 3
    It seems like C++ has really changed a lot in C++0x!, Interesting stuff. – satnhak Apr 16 '11 at 14:19
  • 1
    it's a clearer syntax then the common practice of hiding those methods in a `private` section, and only *declaring* but not *defining* them. – towi May 27 '11 at 08:03

2 Answers2

26

In addition to Xeo's answer:

Yes, everything is correct. If you wanted you could eliminate all of the deleted members but the deleted copy constructor and deleted copy assignment and have the same effect:

struct Picture {  // Also ok

  // 'explicit': no accidental cast from string to Picture
  explicit Picture(const string &filename) { /* load image from file */ }

  // no copy
  Picture(const Picture&) = delete;

  // no assign
  Picture& operator=(const Picture&) = delete;
};

The explicit declaration of the copy constructor inhibits the implicit generation of the default constructor, move constructor and move assignment members. Having these members explicitly deleted is a matter of taste. Some will probably see it as good documentation. Others may see it as overly verbose.

towi
  • 21,587
  • 28
  • 106
  • 187
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
3

Seems fine to me. The return value of operator= must be a normal reference, even if the object is constructed from a rvalue reference. That is because you can't just compile an lvalue (*this) to an rvalue.
And it should take that rvalue reference per non-const Picture& operator=(Picture&&). How would you move from a constant object? ;)

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • Of course, how silly of me. You are right on both accounts. Let me correct it in the question, so the readers do not learn from my faulty example. – towi Apr 16 '11 at 15:27