Почему stl vector не может содержать объекты сопрограмм?

Я использую сопрограмму в boost1.53, см. Мой код ниже:

boost::coroutines::coroutine<int()> f(std::bind(foo, ...));
std::vector<decltype(f)> container; // it can be compiled
container.push_back(f); // compile error

Ошибка:

no matching function for call to ‘std::vector<boost::coroutines::coroutine<int(),0> >::vector(paracel::coroutine<int>&)’

Обновление: ошибка возникает из-за того, что в 'boost :: coroutines :: coroutine' нет конструкции / оператора копирования, в данном случае я хочу сохранить только 'f в контейнер, который сопоставляет индекс с' f '.

Еще пробовал unordered_map и emplace_back, все равно не работает!

Как заставить его работать на C ++?

Update2: я пробовал vector, unordered_map, map вместе с emplace_back, push_back, std :: move, и все не удалось. Но list и deque подходят для push_back / emplace_back и std :: move:

std::deque<decltype(f)> container1;
container.push_back(std::move(f)); // ok
std::deque<decltype(f)> container2;
container.emplace_back(std::move(f)); // ok
std::list<decltype(f)> container3;
container.push_back(std::move(f)); // ok
std::list<decltype(f)> container4;
container.emplace_back(std::move(f)); // ok

Почему?


person xunzhang    schedule 11.11.2013    source источник


Ответы (4)


Похоже, boost::coroutines::coroutines<int()> не поддерживает конструктор копирования. Однако вы пытаетесь push_back() значение l. Однако вы можете попробовать переместить объект в вектор:

container.push_back(std::move(f));
person Dietmar Kühl    schedule 11.11.2013
comment
Если тип, который вы хотите поместить в вектор, нельзя копировать или перемещать, он не сработает. Вам нужно будет использовать другой контейнер, например, std::deque<...> или std::list<...> и emplace_back() объекты. - person Dietmar Kühl; 11.11.2013

Если вы проверите, например, эту ссылку вы увидите, что содержащийся тип

T должен соответствовать требованиям CopyAssignable и CopyConstructible.

А также

Требования, предъявляемые к элементам, зависят от фактических операций, выполняемых с контейнером. Как правило, требуется, чтобы тип элемента соответствовал требованиям MoveConstructible и MoveAssignable, но многие функции-члены предъявляют более строгие требования.

Если вы проверите coroutine class < / a> вы увидите, что в нем нет ни оператора присваивания копии, ни конструктора копирования. У него есть их варианты перемещения, но, как отмечено во втором абзаце выше, этого не всегда достаточно.

person Some programmer dude    schedule 11.11.2013
comment
@xunzhang: Я не уверен, что этого достаточно, но использование emplace_back вместо push_back, вероятно, было бы началом. - person Jerry Coffin; 11.11.2013

Я использую Boost 1.54, и у меня он работает как с g ++ 4.8.2, так и с clang-3.4 с libc ++:

#include <iostream>
#include <vector>
#include <boost/coroutine/coroutine.hpp>

typedef boost::coroutines::coroutine<int()> coro_t;

void f(coro_t::caller_type& ca)
{
   ca(42);
}

int main()
{
   std::vector<coro_t> coros;
   coro_t foo(&f);
   coros.push_back(std::move(foo));
   coros.emplace_back(&f);
   for(auto& coro : coros)
      std::cout << coro.get() << std::endl;
}

Я собираюсь предположить, что у вас нет рабочей стандартной библиотеки или что назначение перемещения в сопрограмме boost 1.53 не является исключением (вы можете проверить это с помощью std::is_nothrow_move_assignable).

person BenPope    schedule 11.11.2013

две возможности:

1.) разместить сопрограммы на freestore:

std::vector< shared_ptr< coroutine< void >::pull_type > v;
v.push_back( new coroutine< void >::pull_type(...) );

2.) используйте контейнер moveaware (boost.container):

boost::container::vector< coroutine< void >::pull_type > v;
coroutine< void >::pull_type c(...)
v.push_back( boost::move( c) );
person olk    schedule 11.11.2013