Элемент unique_ptr, личный конструктор копирования и конструктор перемещения
Учитывая базовый класс для нескольких производных классов, цель состояла в том, чтобы создать класс-оболочку, который позволял бы контейнеру STL видеть объекты с базовым интерфейсом, хотя на самом деле различные производные классы могут фактически добавляться в контейнер. (См. Получение данных из разнородного std:: list).
После некоторой обработки я придумал новый производный класс, который был оберткой вокруг unique_ptr
в базовый класс. Тем не менее, конструктор перемещения меня запутал.
class Base {
friend class BaseWrapper;
virtual Base * clone () const = 0;
public:
virtual ~Base () {}
//... public interface
};
class Derived : public Base {
//... specific members for derived class
Base * clone () const { return new Derived(*this); }
public:
//... implement public interface
};
class BaseWrapper : public Base {
std::unique_ptr<Base> ptr_;
Base * clone () const { return ptr_->clone(); }
public:
BaseWrapper (const Base &b) : ptr_(b.clone()) {}
//... implement public interface by forwarding to ptr_
};
typedef std::list<BaseWrapper> BaseList;
int main () {
BaseList l;
l.push_back(Derived());
}
Это не компилируется с g ++ 4.7.2.
Теперь для того, чтобы использовать BaseWrapper
Я могу реализовать публичный конструктор перемещения следующим образом:
BaseWrapper (BaseWrapper &&bw) { ptr_.swap(bw.ptr_); }
И это прекрасно работает. Но если я сделаю это приватным, он не скомпилируется.
Тем не менее, я обнаружил, что вместо вышесказанного я могу вместо этого определить частный конструктор "копирования" (конечно, также делает его общедоступным):
BaseWrapper (BaseWrapper &bw) { ptr_.swap(bw.ptr_); }
Может ли кто-нибудь сказать мне, если это должно сработать, и почему или почему нет? Если он должен работать, почему я не могу сделать конструктор перемещения закрытым?
Вы можете перейти по этой ссылке на игрушечную программу, иллюстрирующую вышеупомянутое более полным способом.
1 ответ
[убрал ошибочную диагностику]
Это на самом деле компилируется на GCC 4.8. Похоже гкк 4.7 берет BaseWrapper (const Base &)
как конструктор копирования (который на самом деле не является), и неявно удаляет конструктор перемещения (что было бы ожидаемым поведением, если бы это был действительно конструктор копирования).