Generierung der Elementfunktion verschieben

Code:

#include <iostream>
#include <ios>
#include <string>
#include <type_traits>
#include <memory>

struct value
{
    ~value() = default;
    std::unique_ptr<std::string> s;
};

int main()
{
    std::cout << std::boolalpha;
    std::cout << std::is_move_constructible<value>::value << '\n';
    std::cout << std::is_move_assignable<value>::value    << '\n';

    using str_ptr = std::unique_ptr<std::string>;
    std::cout << std::is_move_constructible<str_ptr>::value << '\n';
    std::cout << std::is_move_assignable<str_ptr>::value    << '\n';

    return 0;
}

Ausgabe (kompiliert mit g ++ v4.7.2,http://ideone.com/CkW1tG):

false
false
true
true

Wie ich erwarte,value ist nicht beweglich konstruierbar und kann nicht bewegt werden, weil:

~value() = default;

ist einBenutzer deklariert Destruktor, der die implizite Erzeugung von Bewegungselementen gemäß Abschnitt verhindert12.8 (siehe unten). Wenn der Destruktor dann entfernt wirdvalue ist move konstruierbar und move zuweisbar, wie ich es erwarte (http://ideone.com/VcR2eq).

Wenn jedoch die Definition vonvalue wird geändert in (http://ideone.com/M8LHEA):

struct value
{
    ~value() = default;
    std::string s;      // std::unique_ptr<> removed
};

die Ausgabe ist:

true
true
true
true

value ist unerwartet beweglich konstruierbar und beweglich zuweisbar. Verstehe ich das falsch oder handelt es sich um einen Compiler-Fehler?

Hintergrund: Ich gab eine Antwort aufdiese Frage und wurde darüber informiertTree<> war beweglich, aber ich bin nicht sicher und versuche mit Sicherheit festzustellen, ob es ist oder nicht.

Sektion8.4.2 Explizit voreingestellte Funktionen des c ++ 11-Standards (Entwurf n3337):

Explizit standardisierte Funktionen und implizit deklarierte Funktionen werden zusammen als standardisierte Funktionen bezeichnet, und die Implementierung muss implizite Definitionen für sie bereitstellen (12.1, 12.4, 12.8), was bedeuten kann, dass sie als gelöscht definiert werden. Eine spezielle Member-Funktion wird vom Benutzer bereitgestellt, wenn sie vom Benutzer deklariert und bei der ersten Deklaration nicht explizit als Standard festgelegt oder gelöscht wurde. Eine vom Benutzer bereitgestellte explizit voreingestellte Funktion (d. H. Nach ihrer ersten Deklaration explizit voreingestellt) wird an dem Punkt definiert, an dem sie explizit voreingestellt ist. Wenn eine solche Funktion implizit als gelöscht definiert ist, ist das Programm fehlerhaft. [Hinweis: Wenn Sie eine Funktion nach ihrer ersten Deklaration als Standard deklarieren, können Sie sie effizient ausführen und präzise definieren, während Sie gleichzeitig eine stabile binäre Schnittstelle zu einer sich entwickelnden Codebasis aktivieren.]

Sektion12.8 Kopieren und Verschieben von Klassenobjekten (Punkt 9):

If the definition of a class X does not explicitly declare a move constructor,
one will be implicitly declared as defaulted if and only if
- X does not have a user-declared copy constructor,
- X does not have a user-declared copy assignment operator,
- X does not have a user-declared move assignment operator,
- X does not have a user-declared destructor, and
- the move constructor would not be implicitly defined as deleted.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage