Как на C ++ синтезированный конструктор ходов влияют изменчивые и виртуальные члены?

Посмотрите на следующий код:

struct node
{

  node();
  //node(const node&);    //#1
  //node(node&&);         //#2

  virtual                 //#3
  ~node ();

  node*
  volatile                //#4
  next;

};

int main()
{

  node m(node());         //#5
  node n=node();          //#6
}

При компиляции с gcc-4.6.1 выдает следующую ошибку:

g++ -g --std=c++0x   -c -o node.o node.cc
node.cc: In constructor node::node(node&&):
node.cc:3:8: error: expression node::next has side-effects
node.cc: In function int main():
node.cc:18:14: note: synthesized method node::node(node&&) first required here

Как я понимаю, компилятору не удается создать конструктор перемещения или копирования по умолчанию в строке № 6, если я раскомментирую строку № 1 или № 2, он компилируется нормально, это ясно. Код прекрасно компилируется без опции c ++ 0x, поэтому ошибка связана с конструктором перемещения по умолчанию.

Однако что в классе узла препятствует созданию конструктора перемещения по умолчанию? Если я прокомментирую какую-либо из строк № 3 или № 4 (то есть сделаю деструктор не виртуальным или сделаем элемент данных энергонезависимым), он снова скомпилирует, так что комбинация этих двух не позволяет его компилировать?

Другая загадка, строка № 5, не вызывает ошибку компиляции, чем отличается от строки № 6? Это все специфично для gcc? или gcc-4.6.1?

 Lightness Races in Orbit15 нояб. 2012 г., 23:15
Ты забыл 'mainтип возврата там скиппи

Ответы на вопрос(1)

Решение Вопроса

[C++11: 12.8/9]: Если определение классаX явно не объявляет конструктор перемещения, он будет неявно объявлен как дефолт, если и только если

X не имеет объявленного пользователем конструктора копирования,X не имеет заявленного пользователем оператора копирования,X не имеет объявленного пользователем оператора назначения перемещения,X не имеет объявленного пользователем деструктора, а такжеконструктор перемещения не будет неявно определен как удаленный. [

Замечания: Когда конструктор перемещения не объявляется неявным образом или не предоставляется явно, выражения, которые в противном случае вызвали бы конструктор перемещения, могут вместо этого вызывать конструктор копирования. -конечная нота]

Тот'почему твой # 3 нарушает синтез?

К тому же,Это'далеко не ясно тотизменчивые типы (в том числе вашnode* volatile) тривиально копируемые; можно сделать вывод, чтоэто определяется реализацией, являются ли они или нет и, в вашем случае, кажется, что это не так.

По крайней мере,GCC заставил его перестать работать вполне сознательно в v4.7, с предложением сделать бэкпорт в v4.6.1, который я могу только предположить, пошел вперед ...

Итак, учитывая следующее:

[C++11: 12.8/11]: Неявно объявленный конструктор копирования / перемещения является встроенным открытым членом своего класса.По умолчанию конструктор копирования / перемещения для классаX определяется как удаленный (8.4.3), еслиX имеет:

вариантный член с нетривиальным соответствующим конструктором иX является подобным объединению классом, нестатическим членом данных типа классаM (или их массив), которые нельзя скопировать / переместить из-за разрешения перегрузки (13.3) применительно кMсоответствующий конструктор, приводит к неоднозначности или функции, которая удалена или недоступна из конструктора по умолчанию,прямой или виртуальный базовый классB это не может быть скопировано / перемещено, потому что разрешение перегрузки (13.3), в применении кBсоответствующий конструктор, приводит к неоднозначности или функции, которая удалена или недоступна из конструктора по умолчанию,любой прямой или виртуальный базовый класс или нестатический член данных типа с деструктором, который удален или недоступен из конструктора по умолчанию,для конструктора копирования - нестатический член данных ссылочного типа rvalue илидля конструктора перемещения - нестатический член данных или прямой или виртуальный базовый классс типом, который не имеет конструктора перемещения и не может быть легко скопирован.

... тот'почему ваш # 4 нарушает синтез, независимо от # 3.

Что касается № 5, этона самом деле не декларацияnode вообще, но объявление для функции с именемm - тот'почемуне воспроизводить симптомы, связанные с конструкциейnode (это известно какMost Vexing Parse).

 user182776616 нояб. 2012 г., 19:54
Я бы, если бы у меня было 4.7 :) Мне нужно сохранить 4.6.1, и я нея не хочу иметь две версии gcc параллельно. Но это звучит неправильно, я согласен.
 user182776616 нояб. 2012 г., 16:10
Спасибо, вы сделали это очень ясно. Что меня еще удивляет, так это то, что этот код работает нормально:
 Lightness Races in Orbit16 нояб. 2012 г., 20:13
@ user1827766: виртуализация.
 user182776616 нояб. 2012 г., 16:21
Что меня еще озадачивает, так это то, что этот код работает нормально: struct node {~ node (); узел * volatile следующий; }; и это также: struct node {virtual ~ node (); узел * следующий; }; поэтому gcc-4.6.1 позволяет перемещать ctors для элементов с изменчивыми данными и классов с деструкторами, но почему-то жалуется на сочетание виртуального элемента dtor / volatile.
 Lightness Races in Orbit16 нояб. 2012 г., 17:49
@ user1827766: Можете ли вы попробовать с GCC 4.7? Это звучит неправильно.
 bames5316 нояб. 2012 г., 17:15
Интересно, проблема в том, что volatile является тривиально копируемым, заключается только в атомарной семантике, которую хотят реализовать некоторые реализации. Если так, то мне кажется, что это изменение нене подходит, потому что в ISO C ++ volatile нене имеют атомарной семантики

Ваш ответ на вопрос