Учитывая базовый класс для нескольких производных классов, цель состояла в том, чтобы создать класс-оболочку, который позволял бы контейнеру 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_); }
Может кто-нибудь сказать мне, если это должно было сработать, и почему или почему нет? Если он должен работать, почему я не могу сделать конструктор перемещения закрытым?
Вы можете следовать эта ссылка в игрушечной программе, иллюстрирующей вышесказанное в более полной форме.
Это на самом деле компилируется на GCC 4.8. Похоже гкк 4.7 берет BaseWrapper (const Base &)
как конструктор копирования (который на самом деле не является), и неявно удаляет конструктор перемещения (что было бы ожидаемым поведением, если бы он действительно был конструктором копирования).
Других решений пока нет …