Kod:Move generacja funkcji członka
#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;
}
wyjściowa (skompilowane z g ++ v4.7.2, http://ideone.com/CkW1tG):
false false true true
jak oczekuję, value
nie poruszać constructible i nie przenieść przypisane ponieważ :
~value() = default;
jest deklarowanym przez użytkownika destruktor, który zapobiega niejawnej generacji elementów ruchu zgodnie z sekcją 12.8 (patrz poniżej). Po usunięciu destruktora, value
jest ruchomy i można go przenosić, tak jak się spodziewam (http://ideone.com/VcR2eq).
Jednak, gdy definicja value
zmienia się na (http://ideone.com/M8LHEA):
struct value
{
~value() = default;
std::string s; // std::unique_ptr<> removed
};
wyjście jest:
true true true true
value
niespodziewanie ruszyć constructible i przenieść przypisane. Czy nie rozumiem, czy jest to błąd kompilatora?
Tło: I dały odpowiedź na pytanie this i został poinformowany, że Tree<>
był ruchomy, ale jestem pewien, i 'm próbuje ustalić na pewno, czy jest, czy nie.
Sekcja 8.4.2 Jawnie-zaległych funkcje o standard C++ 11 (Projekt n3337):
Jawnie-zaległych funkcje i niejawnie-zadeklarowane funkcje zwanych zaległych funkcje , a implementacja musi zawierać domyślne definicje (12.1 12.4, 12.8), co może oznaczać definiowanie ich jako usuniętych. Specjalna funkcja składowa jest dostarczana przez użytkownika, jeśli została zadeklarowana przez użytkownika, a jawnie niewpisana domyślnie lub usunięta przy pierwszej deklaracji. Podana przez użytkownika jawnie domyślna funkcja (tj. Jawnie domyślnie po pierwszej deklaracji) jest zdefiniowana w punkcie, w którym jest ona domyślnie ustawiona na ; jeśli taka funkcja jest niejawnie zdefiniowana jako usunięta, program jest źle sformułowany. [Uwaga: Deklarowanie funkcji jako domyślnie po pierwszej deklaracji może zapewnić skuteczną realizację i zwięzłą definicję podczas umożliwiając stabilną interfejs binarny do rozwijającej kod base.-end Uwaga]
rozdział 12.8 kopiowania i przenoszenia klasa obiektów (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.
+1 Dzięki, bardzo jasne wyjaśnienie. Czy jesteś ciekaw, czy znasz jakąś cechę, która wyraźnie sprawdza obecność członków ruchu? – hmjd
Nie ma ani jednego. [_ "semantyka języka rdzeniowego nie jest zbyt użyteczna dla pisarza biblioteki, nie obchodzi go, czy klasa ma coś, co język podstawowy uważa za konstruktor kopii, chcą wiedzieć, czy faktycznie pisze T (someT) zadziała, bez względu na to, czy wywoła konstruktor kopiowania, konstruktor ruchu, konstruktor szablonów lub jakikolwiek konstruktor. "_] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/ n3142.html) Można jednak sprawdzić wartość 'is_move_constructible :: value &&! is_copy_constructible :: value' –