Implicit Move Won’t Go!

1991

Marshall Cline coins the term “Rule of Three“, referring to the practice of explicitly defining the C++ Copy Constructor, Copy Assignment Operator, and Destructor together as a unit (where one is needed, likely the others are, too).  The key reason for this rule was the implicit generation of copy even when they could cause harm.

2002

n1377 – A Proposal to Add Move Semantics Support to the C++ Language – is submitted for consideration for C++0x, adding two new implicit functions: a Move Constructor and Move Assignment Operator.

2010

Various Sources point out several significant problems with generating implicit move constructors and move assignment operators.  The problems occur for reasons related to the original raison d’etre of the “Rule of Three”, and I considered the need for a new “Rule of Five”.  If C++0x was to be a new language, a “Rule of Five” may have sufficed.  But it isn’t.  Current C++ code which is 100% correct could suddenly become broken due to implicit move generation.  A programming “rule of thumb” was clearly not sufficient this time around, and something had to change.

November 2010

The C++0x standards committee meeting had as its biggest issue the task of figuring out how to fix this problem, or otherwise completely remove implicit move.  Thankfully, the issue was resolved by putting strict (but coherent) limitations on when implicit move is generated, but without eliminating implicit move altogether.

I consider the new rules an enforcement of a milder version of the “rule of five” by the compiler.  Due to backwards compatibility the “rule of three” subset cannot be enforced, only deprecated.

Woot!

So we will still have implicit move in C++0x, with coherent compiler enforced limitations on generation which actually add value to boot.

I have created a diagram to outline the new dependencies, where a directed edge means “won’t be implicitly defined if this is explicitly defined”.  Green means “actually enforced”, blue means “merely deprecated”:

Class Member Default Dependancy Graph

Notice that an implicit destructor is not dependent on anything.  In practice, move/copy constructor/assignment are so tightly coupled that they can be grouped together.

I find this easier to visualize in this form:

Class Member Default Dependancy Code

Note…

These diagrams only describe a subset of conditions which must be met before implicit functions will be generated.

You can read all the rules in the current Draft Standard, but my rule-of-thumb is:

  • Copy Constructor: members and base classes must be copyable, and cannot have any rvalue reference members.
  • Move Constructor: members and base classes must be movable or trivially copyable.
  • Copy Assignment: members and base classes must be copy assignable, and cannot have any const or reference members.
  • Move Assignment: members and base classes must be move assignable, and cannot have any const or reference members.

Final Thoughts

Rvalue references and move semantics are extremely powerful and cool features, and not only because of potential efficiency gains.

Copy can be hard (or impossible) to implement, and move gives us more expressiveness in designs, and that is a wonderful thing.

Implicit move is important for both consistency (why should copy be implicit and special?) and for making use of this outstanding feature far less tedious.

I congratulate the C++ standards committee on this conclusion.

About these ads

3 Comments

Filed under cpp0x, Software

3 responses to “Implicit Move Won’t Go!

  1. I have no clue what you mean by saying that

    they resolved the issue by proposing that a milder version of the “Rule of Five” actually be enforced by the compiler

    The “Rule of Three” from which you derive the “Rule of Five” is a guideline for programmers, and that’s precisely because the compiler can’t enforce it.

    • Dave,
      First, I would like to thank you so very much for taking the time to read and comment on my humble little post. I am surprised that you have found it (perhaps that is due to some WordPress magic).

      What I mean is: the guideline for programmers (I called it rule of thumb) existed to remind them of when they needed to explicitly define, not how to.

      I consider the new draft standard rules for when to generate implicit move to serve the same purpose. If you explicitly define some subset of the five, those which would be dangerous to default will not be defaulted, and your code will not compile if you try to use them. Currently, the “rule of three” is left entirely to the programmer to remember, and code will compile fine even if you forget.

      The “rule of three” dependencies will not be enforced for compatability reasons, though they will be depricated (and I assume that implies warnings will be generated – thats good enough for me).

      The beauty of this is that it was proposed in order to keep old code from breaking, but I really think it will pay off dividends even moving forward(!) for novices and experts alike.

      The reason for this post was really not to get hung up on my layman’s terms understanding of the history (I am no expert), but to visually show the current state of things. I was curious if you thought my diagrams were sufficiently correct?

  2. Pingback: W00t W00t Nix Nix! « C++Next

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s