boost::signals::scoped_connection не работает в std::vector. Зачем?

Насколько я понимаю, scoped_connection предназначены для автоматического отключения, когда они выходят за рамки, а не раньше. Я обнаружил, что это не работает правильно, когда scoped_connection находится в std::vector (и, вероятно, не работает и для других контейнеров).

eg.

using boost::signals::scoped_connection; // just for readability
boost::signal<void ()> sig;
std::vector<scoped_connection> connection_vec;

connection_vec.push_back(sig.connect(foo));
assert(connection_vec.back().connected()); // this assertion fails!

Я видел, как это объяснялось утверждением, что std::vector требует, чтобы элементы были копируемыми, тогда как scoped_connection не копировались, но это не совсем так. std::vector требуется только, чтобы элементы были перемещаемыми. (И я ожидаю, что scoped_connection должен быть подвижным.)

Например, работает следующий код:

std::vector<std::unique_ptr<scoped_connection>> vec2;
// Note that std::unique_ptr is uncopyable, but moveable

vec2.push_back(std::unique_ptr<scoped_connection>(new scoped_connection(sig.connect(foo))));
assert((*vec2.back()).connected()); // this assertion succeeds!

Кроме того, если проблема возникла из-за того, что std::vector пытался скопировать некопируемую вещь, то не должно ли это привести к ошибке компиляции?

Поэтому мне интересно, какова фактическая причина того, что scoped_connection работает неправильно внутри vector, и можно ли решить эту проблему в Boost.

(Я тестировал это на gcc версии 4.8.0 с версией boost 1.53.0.)


person karadoc    schedule 19.04.2013    source источник
comment
Это С++11? Или нет? Какие флаги вы передаете gcc?   -  person David Schwartz    schedule 19.04.2013


Ответы (2)


scoped_connection не имеет конструктора перемещения (пока ). Таким образом, он не перемещается, как вы предполагаете, вместо этого std::move будет копировать. И, как вы упомянули, вы не можете копировать scoped_connection.

person ronag    schedule 19.04.2013
comment
Считаете ли вы справедливым сказать, что будущая версия boost должна включать конструктор перемещения для scoped_connection и строго соблюдать правило запрета копирования путем удаления copy_constructor? - person karadoc; 20.04.2013
comment
karadoc: Да, в этом есть смысл. На самом деле вы можете сделать это самостоятельно и создать свою собственную версию Boost. - person ronag; 20.04.2013
comment
Это было исправлено уже начиная с Boost 1.56 (обратите внимание на конструктор перемещения и оператор присваивания перемещения). - person rwols; 15.04.2017

Вам нужно использовать emplace_back, push_back копий.

person David Schwartz    schedule 19.04.2013
comment
Это не меняет проблемы. Поскольку emplace_back может привести к копированию существующих элементов при перераспределении памяти. - person ronag; 19.04.2013