Comments (12)
boost.coroutine2 already tests bind in the unit-tests - and does not fail.
Please provide code (preferable a unit-test) that reproduces the problem.
from coroutine2.
This is a complete source file that demonstrates the error using the develop sources of Context and Coroutine2 mentioned above:
#include <functional>
#include <boost/coroutine2/coroutine.hpp>
typedef boost::coroutines2::coroutine<void>::push_type coroutine;
typedef boost::coroutines2::coroutine<void>::pull_type yield_context;
typedef std::vector<coroutine> coroutine_list;
struct Data
{
Data() : done(false) {}
bool done;
};
template<typename R, typename F>
coroutine_list ForEachParallel(R& r, const F& f)
{
coroutine_list coros;
for (auto& i : r)
{
coros.emplace_back(std::bind(f, std::ref(i), std::placeholders::_1));
}
return coros;
}
struct Test
{
Test();
std::vector<Data> m_data;
coroutine_list m_coros;
};
Test::Test()
{
m_data.resize(5);
m_coros = ForEachParallel(m_data, [](Data& data, yield_context& yield)
{
while (!data.done) yield();
});
}
void main()
{
Test test;
// we don't even need to call the coroutines to generate the error
}
It could probably be further simplified, but this seems short enough. As noted previously, equivalent code to this compiles and runs correctly with both coroutine1 and coroutine2 with VS2015, and with coroutine1 but not coroutine2 using GCC or clang.
from coroutine2.
Actually correction: making the function parameter of ForEachParallel either F f
or const F& f
rather than F& f
lets the above compile ok in clang, but still not gcc. Although I was still getting an issue compiling my full code with clang, but perhaps the error came from a different usage.
from coroutine2.
next time add the compiler out put, please!
your code is ill-formed - you have to pass the functions as rvalue-references:
template<typename R, typename F>
coroutine_list ForEachParallel(R& r, F&& f)
...
coros.emplace_back(std::bind(std::forward(f), std::ref(i), std::placeholders::_1));
from coroutine2.
The compiler output was in the original thread that I linked at the top. Also, not only does the error still occur if using an rvalue-reference, that usage is illegal because it means that bind could potentally move-from the same object multiple times. While that is probably harmless on a lambda object, it's still bad practice.
from coroutine2.
I was able to compile your code (with modifications) with gcc-6.3.1, clang-3.9.1, intel-17.0.1 - I used the code from branch develop
from coroutine2.
your code generates errors like:
clang:
no matching function for call to 'ForEachParallel'
m_coros = ForEachParallel(m_data, [](Data& data, yield_context& yield)
^~~~~~~~~~~~~~~
fibonacci.cpp:26:16: note: candidate function [with R = std::vector<Data, std::allocator >, F = (lambda at fibonacci.cpp:47:39)] not viable: expects an l-value for 2nd argument
coroutine_list ForEachParallel(R& r, F& f)
intel:
no instance of function template "ForEachParallel" matches the argument list
argument types are: (std::vector<Data, std::allocator>, lambda [](Data &, yield_context &)->void)
m_coros = ForEachParallel(m_data, [](Data& data, yield_context& yield)
fibonacci.cpp(26): note: this candidate was rejected because arguments do not match
coroutine_list ForEachParallel(R& r, F& f)
from coroutine2.
With
template<typename R, typename F>
coroutine_list ForEachParallel(R& r, F&& f)
F&& -> F& (reference collapsing) for lvalue-references
F&& a rvalue-reference for temporaries
keep in mind that 'f' becomes in both cases an lvalue
from coroutine2.
Yes, but using std::forward
on that lvalue will convert it back to an rvalue reference (if it was not originally an lvalue), which might get moved-from when passed on (to bind
in this case), so it's illegal to do that inside a loop. You're correct that the parameter can be specified as F&&
without issue, but that's of little practical benefit and might be confusing. const F&
is safest.
The error matching lvalue second parameter sounds like you're using the wrong version of the code -- I had accidentally omitted the const
in the original post, which I corrected a few minutes later; see the updated version of the code in the issue. (An unfortunate side effect of VC's non-const extension rules, so it compiled fine there.) This is not the error I'm talking about.
Again the "real" error messages were posted in the original Boost thread, but for avoidance of confusion here they are again (updated for this test code):
In file included from /mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/coroutine.hpp:49:0,
from /mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/coroutine.hpp:15,
from test.cpp:3:
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/push_control_block_cc.ipp: In instantiation of ‘boost::coroutines2::detail::push_coroutine<void>::control_block::control_block(boost::context::preallocated, StackAllocator, Fn&&) [with StackAllocator = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>]’:
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/create_control_block.ipp:51:68: required from ‘ControlBlock* boost::coroutines2::detail::create_control_block(StackAllocator, Fn&&) [with ControlBlock = boost::coroutines2::detail::push_coroutine<void>::control_block; StackAllocator = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>]’
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/push_coroutine.ipp:158:81: required from ‘boost::coroutines2::detail::push_coroutine<void>::push_coroutine(StackAllocator, Fn&&) [with StackAllocator = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>]’
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/push_coroutine.ipp:153:62: required from ‘boost::coroutines2::detail::push_coroutine<void>::push_coroutine(Fn&&) [with Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>; <template-parameter-1-2> = void]’
/usr/include/c++/4.8/ext/new_allocator.h:120:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = boost::coroutines2::detail::push_coroutine<void>; _Args = {std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>}; _Tp = boost::coroutines2::detail::push_coroutine<void>]’
/usr/include/c++/4.8/bits/alloc_traits.h:254:4: required from ‘static typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = boost::coroutines2::detail::push_coroutine<void>; _Args = {std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>}; _Alloc = std::allocator<boost::coroutines2::detail::push_coroutine<void> >; typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type = void]’
/usr/include/c++/4.8/bits/alloc_traits.h:393:57: required from ‘static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = boost::coroutines2::detail::push_coroutine<void>; _Args = {std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>}; _Alloc = std::allocator<boost::coroutines2::detail::push_coroutine<void> >; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’
/usr/include/c++/4.8/bits/vector.tcc:97:40: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>}; _Tp = boost::coroutines2::detail::push_coroutine<void>; _Alloc = std::allocator<boost::coroutines2::detail::push_coroutine<void> >]’
test.cpp:22:9: required from ‘coroutine_list ForEachParallel(R&, const F&) [with R = std::vector<Data>; F = Test::Test()::__lambda6; coroutine_list = std::vector<boost::coroutines2::detail::push_coroutine<void> >]’
test.cpp:41:6: required from here
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/push_control_block_cc.ipp:332:44: error: call of overloaded ‘callcc(const std::allocator_arg_t&, boost::context::preallocated&, boost::context::basic_fixedsize_stack<boost::context::stack_traits>&, boost::coroutines2::detail::wrapper<boost::coroutines2::detail::push_coroutine<void>::control_block::control_block(boost::context::preallocated, StackAllocator, Fn&&) [with StackAllocator = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>]::__lambda5, std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)> >)’ is ambiguous
std::forward< Fn >( fn) ) );
^
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/push_control_block_cc.ipp:332:44: note: candidates are:
In file included from /mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/pull_control_block_cc.hpp:14:0,
from /mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/detail/coroutine.hpp:37,
from /mnt/ThirdParty/boost/boost_1_63_0/include/boost/coroutine2/coroutine.hpp:15,
from test.cpp:3:
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/context/continuation.hpp:474:1: note: boost::context::continuation boost::context::callcc(std::allocator_arg_t, StackAlloc, Fn&&, Arg ...) [with StackAlloc = boost::context::preallocated; Fn = boost::context::basic_fixedsize_stack<boost::context::stack_traits>&; Arg = {boost::coroutines2::detail::wrapper<boost::coroutines2::detail::push_coroutine<void>::control_block::control_block(boost::context::preallocated, StackAllocator, Fn&&) [with StackAllocator = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>]::__lambda5, std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)> >}]
callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Arg ... arg) {
^
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/context/continuation.hpp:488:1: note: boost::context::continuation boost::context::callcc(std::allocator_arg_t, boost::context::preallocated, StackAlloc, Fn&&, Arg ...) [with StackAlloc = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = boost::coroutines2::detail::wrapper<boost::coroutines2::detail::push_coroutine<void>::control_block::control_block(boost::context::preallocated, StackAllocator, Fn&&) [with StackAllocator = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>]::__lambda5, std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)> >; Arg = {}]
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Arg ... arg) {
^
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/context/continuation.hpp:519:1: note: boost::context::continuation boost::context::callcc(std::allocator_arg_t, boost::context::preallocated, StackAlloc, Fn&&) [with StackAlloc = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = boost::coroutines2::detail::wrapper<boost::coroutines2::detail::push_coroutine<void>::control_block::control_block(boost::context::preallocated, StackAllocator, Fn&&) [with StackAllocator = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>]::__lambda5, std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)> >]
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
^
/mnt/ThirdParty/boost/boost_1_63_0/include/boost/context/continuation.hpp:462:1: note: boost::context::continuation boost::context::callcc(Fn&&, Arg ...) [with Fn = const std::allocator_arg_t&; Arg = {boost::context::preallocated, boost::context::basic_fixedsize_stack<boost::context::stack_traits>, boost::coroutines2::detail::wrapper<boost::coroutines2::detail::push_coroutine<void>::control_block::control_block(boost::context::preallocated, StackAllocator, Fn&&) [with StackAllocator = boost::context::basic_fixedsize_stack<boost::context::stack_traits>; Fn = std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)>]::__lambda5, std::_Bind<Test::Test()::__lambda6(std::reference_wrapper<Data>, std::_Placeholder<1>)> >}; <template-parameter-1-3> = void]
callcc( Fn && fn, Arg ... arg) {
^
Perhaps this is a bug in gcc 4.8 then. So I'll just continue using coroutine1 in the meantime.
from coroutine2.
as I suggested - do you use the code from branch develop (e.g. forthcoming boost-1.64)?
if I change you code to:
coroutine_list ForEachParallel(R& r, F f)
or
coroutine_list ForEachParallel(R& r, F const& f)
it still compiles for gcc-6.3.1, clang-3.9.1 and intel-17.0.1
unfortunately, I can't reproduce your problem
from coroutine2.
Yes, I am using the develop code, and it does compile on clang-3.4. It does not compile on gcc-4.8, as shown above. If it does not reproduce on gcc-6.3, then it's probably a gcc bug, as I said before.
from coroutine2.
If it helps, the build machine I'm using at the moment is based on Ubuntu trusty. gcc 4.8 is the standard compiler in that version, which is why it's using it.
from coroutine2.
Related Issues (20)
- Simple coroutine crash HOT 13
- Boost failed to compile test in coroutine2 lib due to the error C2039 HOT 1
- Undefined behaviour documentation HOT 2
- which detail::forced_unwind should user code propagate: boost::coroutines2 or boost::context? HOT 1
- forced_unwind exception thrown on destroy where no unwind is needed HOT 6
- apply() ambiguity compilation error with C++17 HOT 8
- abi::__forced_unwind is not respected
- test_coroutine_native run where they are not supported HOT 2
- emscripten support? HOT 1
- std::begin and std::end are not overloaded for coroutine<>::pull_type HOT 1
- ASAN Compatibility HOT 2
- Creating a coroutine2 in catch statement results in abort() if an exception is raised. HOT 5
- Crash on cygwin x64 HOT 4
- Refactor the API (possibly adding overhead) to fix a corner case
- Boost\libs\coroutine2 failed to build due to error C2668 on MSVC. HOT 1
- How coroutine2 communicates between coroutines HOT 7
- ambiguous call to begin end for coroutine<>::pull_type breaks range-based for (C++17 mode)
- C++20 not supported HOT 5
- Same executable behaves differently (exception handling) being run with Wine and in native Windows HOT 1
- unable to create not-a-coroutine HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from coroutine2.