Допустим, у меня есть это:
struct Base {
virtual void swap();
Expensive mem;
};
struct Left : Base {
void swap() override;
};
struct Right : Base {
void swap() override;
};
Учитывая vector<shared_ptr<Base>> foo
который содержит Left
а также Right
объекты. Допустим, элемент 13 был Left
теперь я хочу, чтобы это было Right
, Я могу сделать что-то вроде:
foo[13] = make_shared<Right>();
Но теперь давайте предположим, что Expensive
очень дорого строить или копировать, и давайте предположим, что Left
а также Right
не содержат собственных членов, они просто другой способ манипулирования и интерпретации mem
, Есть ли способ, которым я могу разыграть или сказать элементу 13, что теперь он Right
не разрушая Left
что там было? Могу ли я использовать enable_shared_from_this
или подобное манипулировать уничтожением и реконструкцией, где я мог бы позвонить foo[13].swap()
и это «стало бы» Right
?
Ну, вы могли бы рассмотреть возможность Left
а также Right
того же типа. Но если вы не можете этого сделать, тогда вы все равно можете воспользоваться семантикой перемещения. Предполагать Expensive
дешево перемещается. Тогда вы можете сделать что-то вроде этого:
struct Base {
Base(Expensive mem) : mem(std::move(mem)) {}
virtual std::shared_ptr<Base> swap() = 0;
Expensive mem;
};
struct Left : Base {
Left(Expensive mem) : Base(std::move(mem)) {}
std::shared_ptr<Base> swap() override;
};
struct Right : Base {
Right(Expensive mem) : Base(std::move(mem)) {}
std::shared_ptr<Base> swap() override;
};
std::shared_ptr<Base> Left::swap() {
return std::make_shared<Right>(std::move(mem));
}
std::shared_ptr<Base> Right::swap() {
return std::make_shared<Left>(std::move(mem));
}
// ...
foo[13] = foo[13]->swap();
(Обратите внимание, что уничтожение исходного объекта, указанного foo[13]
не происходит, пока тело std::shared_ptr<Base>::operator=
вводится, к которому времени swap()
будет завершен и ушел mem
в разрушаемом состоянии, поэтому мне кажется, что этот код будет четко определен).
Других решений пока нет …