Ответ 1
[C++11: 12.8/9]:
Если определение классаX
явно не объявляет конструктор перемещения, оно будет объявлено как неявное как дефолтное, если и только если
X
не имеет объявленного пользователем конструктора копирования,X
не имеет объявленного пользователем оператора назначения копирования,X
не имеет объявленного пользователем оператора назначения перемещения,X
не имеет объявленного пользователем деструктора и- конструктор перемещения не будет неявно определен как удаленный.
[Примечание. Если конструктор перемещения неявно не объявлен или явно не указан, выражения, которые в противном случае мог бы вызвать конструктор перемещения, может вместо этого вызвать конструктор копирования. -end note]
Вот почему ваш № 3 нарушает синтез.
Кроме того, это далеко не ясно, что летучие типы (включая ваш node* volatile
) тривиально копируются; можно сделать вывод, что определяется реализацией, являются они или нет, и в вашем случае кажется, что это не так.
По крайней мере, GCC заставил его перестать работать совершенно преднамеренно в версии 4.7, с предложением включить в v4.6.1 Я могу только предположить, пошел вперед...
Итак, учитывая следующее:
[C++11: 12.8/11]:
Неявно объявленный конструктор copy/move является встроенным публичным членом своего класса. Конструктор копирования/перемещения по умолчанию для классаX
определяется как удаленный (8.4.3), еслиX
имеет:
- вариантный член с нетривиальным соответствующим конструктором и
X
является объединенным классом, нестатический элемент данных типа классаM
(или его массив), которые невозможно скопировать/перемещать, поскольку разрешение перегрузки (13.3), применимое к соответствующему конструкторуM
, приводит к неоднозначности или функции, которая удалена или недоступен из конструктора, установленного по умолчанию,- прямой или виртуальный базовый класс
B
, который не может быть скопирован/перемещен, поскольку разрешение перегрузки (13.3) применительно к соответствующему конструкторуB
приводит к двусмысленности или функции, которая удалена или недоступна по умолчанию конструктор,- любой прямой или виртуальный базовый класс или нестатический член данных типа с деструктором, который удален или недоступен из конструктора, установленного по умолчанию,
- для конструктора копирования, нестатического элемента данных ссылочного типа rvalue или
- для конструктора перемещения, нестатического элемента данных или прямого или виртуального базового класса с типом, который не имеет конструктора перемещения и не является тривиально скопируемым.
... почему ваш # 4 также нарушает синтез, независимо от № 3.
Что касается № 5, это вообще не декларация node
, а объявление для функции с именем M
— почему он не воспроизводит симптомы, связанные со строительством node
(это называется Most Vexing Parse).