| // Check that we obey the extra rules for implicitly movable co_return |
| // objects [class.copy.elision]/3. |
| |
| #include "coro.h" |
| |
| #include <utility> |
| |
| template <typename T> |
| struct coro1 { |
| struct promise_type; |
| using handle_type = coro::coroutine_handle<coro1::promise_type>; |
| handle_type handle; |
| coro1 () : handle(0) {} |
| coro1 (handle_type _handle) |
| : handle(_handle) { } |
| coro1 (const coro1 &) = delete; // no copying |
| coro1 (coro1 &&s) : handle(s.handle) { s.handle = nullptr; } |
| coro1 &operator = (coro1 &&s) { |
| handle = s.handle; |
| s.handle = nullptr; |
| return *this; |
| } |
| ~coro1() { |
| if ( handle ) |
| handle.destroy(); |
| } |
| |
| struct promise_type { |
| T value; |
| promise_type() {} |
| ~promise_type() {} |
| |
| auto get_return_object () { return handle_type::from_promise (*this);} |
| coro::suspend_always initial_suspend () const { return {}; } |
| coro::suspend_always final_suspend () const noexcept { return {}; } |
| |
| void return_value(T&& v) noexcept { value = std::move(v); } |
| void return_value(const T&) noexcept = delete; |
| |
| T get_value (void) { return value; } |
| void unhandled_exception() { } |
| }; |
| }; |
| |
| struct MoveOnlyType |
| { |
| int value_; |
| |
| explicit MoveOnlyType() noexcept : value_(0) {} |
| explicit MoveOnlyType(int value) noexcept : value_(value) {} |
| |
| MoveOnlyType(MoveOnlyType&& other) noexcept |
| : value_(std::exchange(other.value_, -1)) {} |
| |
| MoveOnlyType& operator=(MoveOnlyType&& other) noexcept { |
| value_ = std::exchange(other.value_, -1); |
| return *this; |
| } |
| |
| ~MoveOnlyType() { value_ = -2; } |
| }; |
| |
| bool b1, b2; |
| |
| coro1<MoveOnlyType> |
| my_coro (MoveOnlyType p, MoveOnlyType &&r) |
| { |
| MoveOnlyType x{10}; |
| if (b1) |
| co_return p; |
| else if (b2) |
| co_return r; |
| else |
| co_return x; |
| } |