[Boost-bugs] [Boost C++ Libraries] #10664: Missing support with respect to moves

Subject: [Boost-bugs] [Boost C++ Libraries] #10664: Missing support with respect to moves
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2014-10-16 09:42:36


#10664: Missing support with respect to moves
------------------------------+-----------------------
 Reporter: anonymous | Owner: olli
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: coroutine
  Version: Boost 1.56.0 | Severity: Problem
 Keywords: |
------------------------------+-----------------------
 Some parts of the documentation suggests that coroutines can be used with
 move-only types (e.g.
 boost::coroutines::asymmetric_coroutine<std::unique_ptr<int>>):

> If R is a move-only type, you may only call get() once before the next
 asymmetric_coroutine<>::pull_type::operator() call.

> However, if the template parameter is a move-only type,
 symmetric_coroutine<>::yield_type::get() may only be called once before
 the next symmetric_coroutine<>::yield_type::operator() call.

 However those get members are implemented as some form of return *
 result_;, where the result type is that move-only type. This rightfully
 won't work.

 Note that using the input iterator (in the asymmetric case) works, because
 its operator* uses the get_pointer() member (of the non-public
 implementation) rather than get().

 My first thought on how to solve this is to elaborate the public
 interface, as I believe only one get() member won't cut it. Even if e.g.
 get() performs some equivalent of return move(*result_); for move-only
 types, there is a missed opportunity for copyable types that have an
 optimized move. Consider a coroutine of std::vector<int>, for which we
 only call get() at most once per value yielded: we would like each value
 to be passed around with moves, to avoid unnecessary allocations.

 IOW, there is a clear separation of concerns between a getter that can be
 called at most once, for which returning by value is a natural fit; and a
 getter that can be called any number of times, for which returning by
 value is not unheard of, but in which case it shouldn't compile for move-
 only types--although the presence and uses of get_pointer() suggests a
 need for returning by reference. This makes it possible at all to write
 correct generic code, too:

 {{{
 auto f(Functor functor, Coro& coro)
 {
     // for a double-duty get(), we can't tell if
     // we're performing two moves (which is bad)
     // or two copies (which could be inefficient)
     return functor(coro.get(), coro.get());

     // okay: this won't compile for move-only types, and
     // this performs the required work when we really need
     // additional copies
     return functor(coro.get_copy(), coro.get_copy());
     // a savvy programmer that wants as few copies as possible,
     // when moves are assumed to be acceptable, has the tools
     // to achieve that goal:
     auto copy = coro.get_copy();
     return functor(move(copy), move(coro.get_reference()));
     // minimal work: one copy, one move
     // possible thanks to the sequencing guarantees of { }
     return Foo { coro.get_copy(), move(coro.get_reference) };

     // okay, doesn't even require moveability
     return functor(coro.get_reference(), coro_get_reference());

     // not okay, can't be caught by the compiler but hopefully
     // obvious to the programmer
     return functor(coro.get_move(), coro.get_move());
 }
 }}}

 (The names are painfully spelled out for the purpose of illustration and
 not a serious suggestion.)

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/10664>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:17 UTC