Title
Explicitly vs implicitly deleted move constructors
Status
nad
Section
11.4.5.3 [class.copy.ctor]
Submitter
Vinny Romano

Created on 2014-01-13.00:00:00 last changed 123 months ago

Messages

Date: 2014-02-15.00:00:00

Rationale (February, 2014):

The specification is as intended.

Date: 2022-11-20.07:54:16

According to 11.4.5.3 [class.copy.ctor] paragraph 11,

A defaulted move constructor that is defined as deleted is ignored by overload resolution (12.2 [over.match], 12.3 [over.over]). [Note: A deleted move constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead. —end note]

Limiting this provision to defaulted move constructors introduces an unfortunate distinction between implicitly and explicitly deleted move constructors. For example, given

  #include <iostream>
  #include <memory>
  using namespace std;

  struct Expl {
    Expl() = default;
    Expl(const Expl &) {
      cout << " Expl(const Expl &)" << endl;
   }
   Expl(Expl &&) = delete;
  };

  struct Impl : Expl {
    Impl() = default;
    Impl(const Impl &) {
      cout << " Impl(const Impl &)" << endl;
    }
    Impl(Impl &&) = default;
  };

  struct Moveable {
    Moveable() { }
    Moveable(const Moveable &) {
      cout << " Moveable(const Moveable &)" << endl;
    }
    Moveable(Moveable &&) {
      cout << " Moveable(Moveable &&)" << endl;
    }
  };

  template<typename T> struct Container {
    Moveable moveable[2];
    T t;
  };

  int main() {
    cout << "Expl:" << endl;
    Container<Expl> c1(move(Container<Expl>()));
    cout << "Impl:" << endl;
    Container<Impl> c2(move(Container<Impl>()));
  }

The output of this program is

  Expl:
   Moveable(const Moveable &)
   Moveable(const Moveable &)
   Expl(const Expl &)
  Impl:
   Moveable(Moveable &&)
   Moveable(Moveable &&)
   Impl(const Impl &)

Should the specification be changed to allow overload resolution to ignore all deleted move constructors instead of only the defaulted ones?

From one perspective, at least, the principal reason to delete a move constructor explicitly is to elicit an error if a move is attempted, and such a change would violate that intent. On the other hand, minimizing the difference between explicit default and implicit default seems like an important goal.

History
Date User Action Args
2014-03-03 00:00:00adminsetmessages: + msg4981
2014-03-03 00:00:00adminsetstatus: open -> nad
2014-01-13 00:00:00admincreate