Переместить генерацию функции-члена
Код:
#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;
}
Вывод (скомпилирован с g ++ v4.7.2,http://ideone.com/CkW1tG):
false false true true
Как я и ожидал,value
не может быть перемещаемым и не может быть назначено, потому что:
~value() = default;
этопользователь объявлена деструктор, который предотвращает неявную генерацию элементов перемещения в соответствии с разделом12,8 (Смотри ниже). Если деструктор удален, тоvalue
как и ожидалосьhttp://ideone.com/VcR2eq).
Тем не менее, когда определениеvalue
изменено на (http://ideone.com/M8LHEA):
struct value
{
~value() = default;
std::string s; // std::unique_ptr<> removed
};
выход:
true true true true
value
неожиданно двигаться конструктивно и назначаться. Я неправильно понимаю или это ошибка компилятора?
Фон: Я дал ответэто вопрос и сообщили, чтоTree<>
был подвижен, но я не уверен и пытаюсь определить наверняка, так это или нет.
Раздел8.4.2 Явно-дефолтные функции стандарта c ++ 11 (черновик n3337):
Явно-дефолтные функции и неявно объявленные функции в совокупности называются дефолтными функциями, и реализация должна предоставлять для них неявные определения (12.1, 12.4, 12.8), что может означать их определение как удаленных. Специальная функция-член предоставляется пользователем, если она объявлена пользователем и не имеет явных значений по умолчанию или удалена в первом объявлении. Предоставленная пользователем явно дефолтная функция (т.е. явно дефолтная после ее первого объявления) определяется в точке, где она явно дефолтна; если такая функция неявно определена как удаленная, программа является некорректной. [Примечание: Объявление функции по умолчанию после ее первого объявления может обеспечить эффективное выполнение и краткое определение при одновременном включении стабильного двоичного интерфейса в развивающуюся кодовую базу. - Конечное примечание]
Раздел12.8 Копирование и перемещение объектов класса (пункт 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.