Soweit ich [class.copy.ctor] und [class.copy.assign], struct A
im folgenden Code verstehen sollte nicht bewegen-konstruierbar noch bewegen zuweisbare:Unmögliche implizite Verschiebeoperationen?
#include <type_traits>
struct X {
X() noexcept; // user-declared default constructor
~X() noexcept; // Force X not to be trivially copyable
X(X &&) = delete; // Explicitly deleted move constructor
X(X const &) = delete; // Explicitly deleted copy constructor
X & operator=(X &&) = delete; // Explicitly deleted move assignment operator
X & operator=(X const &) = delete; // Explicitly deleted copy assignment op.
};
static_assert(!std::is_copy_constructible<X>::value, "");
static_assert(!std::is_copy_assignable<X>::value, "");
static_assert(!std::is_move_assignable<X>::value, "");
static_assert(!std::is_move_constructible<X>::value, "");
static_assert(!std::is_trivially_copyable<X>::value, "");
static_assert(!std::is_trivially_copy_assignable<X>::value, "");
static_assert(!std::is_trivially_copy_constructible<X>::value, "");
static_assert(!std::is_trivially_move_assignable<X>::value, "");
static_assert(!std::is_trivially_move_constructible<X>::value, "");
struct A {
A() noexcept; // user-declared default constructor
A(A const &) noexcept; // user-declared copy constructor
A & operator=(A const &) noexcept; // user-declared copy assignment operator
X x;
};
static_assert(std::is_copy_constructible<A>::value, "");
static_assert(std::is_copy_assignable<A>::value, "");
static_assert(!std::is_move_assignable<A>::value, ""); // FAILS?!
static_assert(!std::is_move_constructible<A>::value, ""); // FAILS?!
static_assert(!std::is_trivially_copyable<A>::value, "");
static_assert(!std::is_trivially_copy_assignable<A>::value, "");
static_assert(!std::is_trivially_copy_constructible<A>::value, "");
static_assert(!std::is_trivially_move_assignable<A>::value, "");
static_assert(!std::is_trivially_move_constructible<A>::value, "");
jedoch zwei der statischen Behauptungen scheitern sowohl mit GCC und Clang, die bedeutet, dass aus irgendeinem Grund A
move-assignable und move-constructible ist.
In meiner Argumentation sollte dies nicht sein, denn struct A
:
- nicht explizit einen Umzug Konstruktor
- erklären auch keine Aussage explizit einen Zug Zuweisungsoperator
- ein benutzer erklärt Copykonstruktor hat
- verfügt über einen vom Benutzer deklarierten Kopierzuweisungsoperator.
- hat ein Feld
x
vom TypX
, das nicht mit anderenA::x
direkt initialisiert werden kann, da alle Konstruktoren vonX
, die für die Überladungsauflösung teilnehmen würden, explizit gelöscht werden.
Ist das ein Compiler Bug oder verkenne ich etwas?
@jotik du hast sie nicht von 'A' gelöscht. Gelöscht und nicht generiert sind verschiedene Dinge: Gelöschte Funktionen/Konstruktoren nehmen an der Überladungsauflösung teil, nicht generierte Funktionen nicht. Außerdem wird 'x' member standardmäßig überall initialisiert, da Sie es in benutzerdefinierten Konstruktoren nicht anders angegeben haben. –