Ответ 1
Сбой связан с ограничением g++ 4.7, который не реализует DR 1170, который очень поздно был изменен в процессе стандартизации С++ 11, чтобы скажем, что проверка доступа должна выполняться как часть вывода аргумента шаблона.
Основная причина заключается в том, что libstdС++ vector
будет перемещать элементы, если операция перемещения не будет выбрана (т.е. объявлена noexcept
или throw()
), иначе, если тип скопируется, элементы будут скопированы, иначе если тип не может быть скопирован, но имеет операцию перемещения с возможностью броска, то он будет перемещен (и если исключение будет выбрано, результаты будут undefined неуказаны.) Это выполняется с проверками на is_nothrow_move_constructible
и is_copy_constructible
. В вашем случае тип не является конструктивным, но не проверяется, поэтому проверяется свойство is_copy_constructible
. У вашего типа есть конструктор копирования, но он недоступен, поэтому признак is_copy_constructible
создает ошибку компилятора с g++ 4.7, потому что проверка доступа не выполняется при выводе аргумента шаблона.
Если вы создадите свой конструктор перемещения и переместите оператор присваивания noexcept
, тогда тип будет перемещен и не должен быть скопирован, поэтому признак is_copy_constructible
, который терпит неудачу, не используется, и код компилируется ОК.
В качестве альтернативы (как указано в комментариях), если вы создадите конструктор копии, то свойство is_copy_constructible
получит правильный результат.
Другой альтернативой является использование чего-то типа boost::noncopyable
, который неявно делает конструктор копии удаленным, поэтому признак is_copy_constructible
работает правильно (а также работает со старыми компиляторами, такими как MSVC, которые не поддерживают удаленные функции должным образом). Я не знаю, что вы хотите сказать о невозможности найти ошибку, не показывает ли MSVC полный контекст ошибки компилятора?
Заключение: используйте unique_ptr, если это необходимо, но не делайте классы явно перемещаемыми
Я не согласен с этим заключением, он слишком экстремален. Вместо этого сделайте свои занятия, если это возможно, передвижными. Кроме того, когда это возможно, используйте удаленные функции, чтобы сделать тип не скопированным вместо частных + нереализованных функций, возможно, используя макрос для переносимости для старых компиляторов, например.
#if __cplusplus >= 201103L
#define NONCOPYABLE(TYPE) \
TYPE(const TYPE&) = delete; TYPE& operator=(const TYPE&) = delete
#else
// must be used in private access region
#define NONCOPYABLE(TYPE) \
TYPE(const TYPE&); TYPE& operator=(const TYPE&)
#endif
struct MyStruct
{
...
private:
NONCOPYABLE(MyStruct);
};