Limitations of BOOST_COROUTINES_V2 (pass by reference)

Hi, aside from the fact that the new coroutines are - apparently intentionally - only unidirectional now (currently not much of an issue for me), I noticed that it is apparently no longer possible to yield values by reference as shown in the following example: #include <fstream> #include <string> #include <iostream> #include <boost/coroutine/all.hpp> using type = std::string; auto lines_from_file(char const * fname) -> boost::coroutines::coroutine<type>::pull_type { using namespace boost::coroutines; return coroutine<type>::pull_type{ [fname](coroutine<type>::push_type& yield) { std::string line; std::ifstream stream(fname); while(stream) std::getline(stream, line), yield(line); }, attributes(fpu_not_preserved) }; } int main(int, char**) { auto lines = lines_from_file("test.txt"); unsigned count = 0; for(auto& line : lines) std::cout << std::setw(4) << ++count << ": " << line << "\n"; } If one changes type to std::string const & the example no longer compiles. If I use the old BOOST_COROUTINES_V1 API boost::coroutines::coroutine<std::string const &()> works just fine. Is this limitation also intentional (why?) or is this an unintentional regression? Regards Johannes S. Mueller-Roemer -- Johannes S. Mueller-Roemer, MSc Wiss. Mitarbeiter - Interactive Engineering Technologies (IET) Fraunhofer-Institut für Graphische Datenverarbeitung IGD Fraunhoferstr. 5 | 64283 Darmstadt | Germany Tel +49 6151 155-606 | Fax +49 6151 155-139 johannes.mueller-roemer@igd.fraunhofer.de | www.igd.fraunhofer.de

On Thu, Jul 3, 2014 at 7:55 AM, Mueller-Roemer, Johannes Sebastian <Johannes.Sebastian.Mueller-Roemer@igd.fraunhofer.de> wrote:
aside from the fact that the new coroutines are – apparently intentionally – only unidirectional now (currently not much of an issue for me),
I'm really curious about any real use case that you, or anyone else, might have for bidirectional data flow with a coroutine.
I noticed that it is apparently no longer possible to yield values by reference as shown in the following example:
I must respectfully disagree. I have a working example program using the new syntax that yields temporary values from a polymorphic class hierarchy by const reference.
auto lines_from_file(char const * fname) -> boost::coroutines::coroutine<type>::pull_type { using namespace boost::coroutines; return coroutine<type>::pull_type{ [fname](coroutine<type>::push_type& yield) { std::string line; std::ifstream stream(fname); while(stream) std::getline(stream, line), yield(line); }, attributes(fpu_not_preserved) }; }
int main(int, char**) { auto lines = lines_from_file("test.txt"); unsigned count = 0; for(auto& line : lines) std::cout << std::setw(4) << ++count << ": " << line << "\n"; }
If one changes type to std::string const & the example no longer compiles.
Could it be that auto& isn't matching std::string const&? What if you change auto& to std::string const &?

Sorry for the misunderstanding, the part in the parentheses was meant to point out that I currently do not require bidirectional data flow, so I don't have a use case for that ;) The auto& is not the issue and works just fine in the BOOST_COROUTINES_V1 case (and if it were, it would be a compiler bug as auto& must match std::string const &). Here is the error message using auto& and type=std::string const &: In file included from D:/libs/mingw-amd64/boost_1_55_0/include/boost/optional.hpp:15:0, from D:/libs/mingw-amd64/boost_1_55_0/include/boost/coroutine/v2/coroutine.hpp:17, from D:/libs/mingw-amd64/boost_1_55_0/include/boost/coroutine/coroutine.hpp:11, from D:/libs/mingw-amd64/boost_1_55_0/include/boost/coroutine/all.hpp:11, from D:\projects\coro\coro_getline.cpp:4: D:/libs/mingw-amd64/boost_1_55_0/include/boost/optional/optional.hpp: In instantiation of 'void boost::optional_detail::optional_base<T>::assign(const boost::optional<U>&) [with U = const std::basic_string<char>&; T = const std::basic_string<char>*]': D:/libs/mingw-amd64/boost_1_55_0/include/boost/optional/optional.hpp:588:9: required from 'boost::optional<T>& boost::optional<T>::operator=(const boost::optional<U>&) [with U = const std::basic_string<char>&; T = const std::basic_string<char>*]' D:/libs/mingw-amd64/boost_1_55_0/include/boost/coroutine/v2/detail/pull_coroutine_base.hpp:227:17: required from 'void boost::coroutines::detail::pull_coroutine_base<R&>::pull() [with R = const std::basic_string<char>]' D:/libs/mingw-amd64/boost_1_55_0/include/boost/coroutine/v2/coroutine.hpp:1592:9: required from 'boost::coroutines::pull_coroutine<R&>& boost::coroutines::pull_coroutine<R&>::operator()() [with R = const std::basic_string<char>]' D:/libs/mingw-amd64/boost_1_55_0/include/boost/coroutine/v2/coroutine.hpp:1630:21: required from 'void boost::coroutines::pull_coroutine<R&>::iterator::increment_() [with R = const std::basic_string<char>]' D:/libs/mingw-amd64/boost_1_55_0/include/boost/coroutine/v2/coroutine.hpp:1666:24: required from 'boost::coroutines::pull_coroutine<R&>::iterator& boost::coroutines::pull_coroutine<R&>::iterator::operator++() [with R = const std::basic_string<char>]' D:\projects\coro\coro_getline.cpp:26:19: required from here D:/libs/mingw-amd64/boost_1_55_0/include/boost/optional/optional.hpp:293:88: error: invalid static_cast from type 'boost::optional_detail::types_when_is_ref<const std::basic_string<char>&>::raw_type {aka const std::basic_string<char>}' to type 'boost::optional_detail::optional_base<const std::basic_string<char>*>::value_type {aka const std::basic_string<char>*}' assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() ); ^ D:/libs/mingw-amd64/boost_1_55_0/include/boost/optional/optional.hpp:299:55: error: invalid static_cast from type 'boost::optional_detail::types_when_is_ref<const std::basic_string<char>&>::raw_type {aka const std::basic_string<char>}' to type 'boost::optional_detail::optional_base<const std::basic_string<char>*>::value_type {aka const std::basic_string<char>*}' construct(static_cast<value_type>(rhs.get())); ^ Using std::string const & instead of auto results in an *identical* error message. An old-style iterator-based for loop produces a nearly identical error. FIY the compiler is GCC 4.9.0 Mingw-w64 (which does have some other issues with boost.context, as the result of the ml64 output produces " corrupt .drectve at end of def file" warnings at link time, but that is unrelated to this issue). -- Johannes S. Mueller-Roemer, MSc Wiss. Mitarbeiter - Interactive Engineering Technologies (IET) Fraunhofer-Institut für Graphische Datenverarbeitung IGD Fraunhoferstr. 5 | 64283 Darmstadt | Germany Tel +49 6151 155-606 | Fax +49 6151 155-139 johannes.mueller-roemer@igd.fraunhofer.de | www.igd.fraunhofer.de -----Original Message----- From: Boost-users [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Nat Goodspeed Sent: Friday, July 04, 2014 02:21 To: boost-users@lists.boost.org Subject: Re: [Boost-users] Limitations of BOOST_COROUTINES_V2 (pass by reference) On Thu, Jul 3, 2014 at 7:55 AM, Mueller-Roemer, Johannes Sebastian <Johannes.Sebastian.Mueller-Roemer@igd.fraunhofer.de> wrote:
aside from the fact that the new coroutines are – apparently intentionally – only unidirectional now (currently not much of an issue for me),
I'm really curious about any real use case that you, or anyone else, might have for bidirectional data flow with a coroutine.
I noticed that it is apparently no longer possible to yield values by reference as shown in the following example:
I must respectfully disagree. I have a working example program using the new syntax that yields temporary values from a polymorphic class hierarchy by const reference.
auto lines_from_file(char const * fname) -> boost::coroutines::coroutine<type>::pull_type { using namespace boost::coroutines; return coroutine<type>::pull_type{ [fname](coroutine<type>::push_type& yield) { std::string line; std::ifstream stream(fname); while(stream) std::getline(stream, line), yield(line); }, attributes(fpu_not_preserved) }; }
int main(int, char**) { auto lines = lines_from_file("test.txt"); unsigned count = 0; for(auto& line : lines) std::cout << std::setw(4) << ++count << ": " << line << "\n"; }
If one changes type to std::string const & the example no longer compiles.
Could it be that auto& isn't matching std::string const&? What if you change auto& to std::string const &? _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Fri, Jul 4, 2014 at 2:28 AM, Mueller-Roemer, Johannes Sebastian <Johannes.Sebastian.Mueller-Roemer@igd.fraunhofer.de> wrote:
Sorry for the misunderstanding, the part in the parentheses was meant to point out that I currently do not require bidirectional data flow, so I don't have a use case for that ;)
I do understand that. My question was directed more to the mailing list in general. I'm content with unidrectional coroutine data flow until someone surfaces a compelling use case for bidirectional.
The auto& is not the issue and works just fine in the BOOST_COROUTINES_V1 case (and if it were, it would be a compiler bug as auto& must match std::string const &).
Could it be a compiler bug anyway? The following works fine with gcc 4.2: #include <boost/coroutine/all.hpp> #include <iostream> void coro_fn(boost::coroutines::coroutine<const std::string&>::push_type& sink) { sink("Hello world!\n"); } int main(int argc, char *argv[]) { boost::coroutines::coroutine<const std::string&>::pull_type coro(coro_fn); std::cout << coro.get() << std::endl; return 0; }

2014-07-04 22:27 GMT+08:00 Nat Goodspeed <nat@lindenlab.com>:
On Fri, Jul 4, 2014 at 2:28 AM, Mueller-Roemer, Johannes Sebastian <Johannes.Sebastian.Mueller-Roemer@igd.fraunhofer.de> wrote:
Sorry for the misunderstanding, the part in the parentheses was meant to point out that I currently do not require bidirectional data flow, so I don't have a use case for that ;)
I do understand that. My question was directed more to the mailing list in general. I'm content with unidrectional coroutine data flow until someone surfaces a compelling use case for bidirectional.
The auto& is not the issue and works just fine in the BOOST_COROUTINES_V1 case (and if it were, it would be a compiler bug as auto& must match std::string const &).
Could it be a compiler bug anyway? The following works fine with gcc 4.2:
#include <boost/coroutine/all.hpp> #include <iostream>
void coro_fn(boost::coroutines::coroutine<const std::string&>::push_type& sink) { sink("Hello world!\n"); }
int main(int argc, char *argv[]) { boost::coroutines::coroutine<const std::string&>::pull_type coro(coro_fn); std::cout << coro.get() << std::endl; return 0; }
Call coro() and you'll see the error. Seems that the specializations of pull_coroutine_base and pull_coroutine_object for R& is unnecessary and erroneous.

- you could use two symmetric coroutines if you want to mimic bidirectional data transfer - your example compiles and works with code from branch develop/master - it might be a regression in 1.55 and should be fixed in 1.56

I just build the current git version and it appears to work now. The "Warning: corrupt .drectve at end of def file" are still produced though. ________________________________ From: Boost-users [boost-users-bounces@lists.boost.org] on behalf of Oliver Kowalke [oliver.kowalke@gmail.com] Sent: Friday, July 04, 2014 5:22 PM To: boost-users Subject: Re: [Boost-users] Limitations of BOOST_COROUTINES_V2 (pass by reference) - you could use two symmetric coroutines if you want to mimic bidirectional data transfer - your example compiles and works with code from branch develop/master - it might be a regression in 1.55 and should be fixed in 1.56

2014-07-05 13:43 GMT+02:00 Mueller-Roemer, Johannes Sebastian < Johannes.Sebastian.Mueller-Roemer@igd.fraunhofer.de>:
I just build the current git version and it appears to work now. The "Warning: corrupt .drectve at end of def file" are still produced though.
you are using mingw? mingw has some problems with objects in MS PE binary format - other compilers (like gcc/clang on UNIX or msvc on WIndows) have no problems.

Yes, as I previously stated I am using GCC 4.9.0 Mingw-w64. Both the ml64 dependency and the warnings are annoying. Never had such issues with regular C object files built with MSVC though. ________________________________ From: Boost-users [boost-users-bounces@lists.boost.org] on behalf of Oliver Kowalke [oliver.kowalke@gmail.com] Sent: Saturday, July 05, 2014 5:46 PM To: boost-users Subject: Re: [Boost-users] Limitations of BOOST_COROUTINES_V2 (pass by reference) 2014-07-05 13:43 GMT+02:00 Mueller-Roemer, Johannes Sebastian <Johannes.Sebastian.Mueller-Roemer@igd.fraunhofer.de<mailto:Johannes.Sebastian.Mueller-Roemer@igd.fraunhofer.de>>: I just build the current git version and it appears to work now. The "Warning: corrupt .drectve at end of def file" are still produced though. you are using mingw? mingw has some problems with objects in MS PE binary format - other compilers (like gcc/clang on UNIX or msvc on WIndows) have no problems.

On Fri, Jul 4, 2014 at 11:22 AM, Oliver Kowalke <oliver.kowalke@gmail.com> wrote:
- your example compiles and works with code from branch develop/master - it might be a regression in 1.55 and should be fixed in 1.56
I tried my little program (earlier in this thread) with 1.56 beta 1, and it works with that Boost package.
participants (4)
-
Mueller-Roemer, Johannes Sebastian
-
Nat Goodspeed
-
Oliver Kowalke
-
TONGARI J