xunzhang
xunzhang

Reputation: 2936

Why stl vector can't contain coroutine objects?

I use coroutine in boost1.53, see my code below:

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

the error:

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

Update: The error is occured because there are no copy construction/operator in 'boost::coroutines::coroutine', case here is I only want to save the 'f's into a container which map a index to 'f'.

I also tried unordered_map, and emplace_back, it still can not work!

How can I make it work in C++?

Update2: I tried vector,unordered_map, map together with emplace_back, push_back, std::move and all failed. But list and deque is ok with push_back/emplace_back and 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

Why?

Upvotes: 2

Views: 822

Answers (4)

BenPope
BenPope

Reputation: 154

I use Boost 1.54 and it works for me with both g++4.8.2 and clang-3.4 with 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;
}

I'm going to speculate that you don't have a working standard library or the move assignment in coroutine of boost 1.53 is not noexcept (you can check that with std::is_nothrow_move_assignable).

Upvotes: 1

olk
olk

Reputation: 400

two possibilities:

1.) allocate the coroutines on freestore:

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

2.) use a moveaware-container (boost.container):

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

Upvotes: 0

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153955

It looks as if boost::coroutines::coroutines<int()> doesn't support a copy constructor. You try to push_back() an lvalue, however. You might want to try moving the object into vector, though:

container.push_back(std::move(f));

Upvotes: 8

Some programmer dude
Some programmer dude

Reputation: 409364

If you check e.g. this reference you will see that the contained type

T must meet the requirements of CopyAssignable and CopyConstructible.

And

The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type meets the requirements of MoveConstructible and MoveAssignable, but many member functions impose stricter requirements.

If you check the coroutine class you will see that it has neither copy-assignment operator nor a copy-constructor. It do have move variants of those, but as noted by the second paragraph above, it's not always enough.

Upvotes: 3

Related Questions