Allow coroutine_handle<const T> to support creation from const references to the promise_type

It seems conceivable that a user would need to get a coroutine handle
having only a const reference to the promise_type, for example from
within a const member function of the promise.

This patch allows that use case. A coroutine_handle<const T> can be used
in essentially the same way a coroutine_handle<T>, ie to start and destroy
the coroutine. The constness of the promise doesn't/shouldn't propagate
to the handle.

llvm-svn: 305536
This commit is contained in:
Eric Fiselier 2017-06-16 00:36:17 +00:00
parent f63d41469c
commit f9bc058935
2 changed files with 39 additions and 2 deletions

View File

@ -250,9 +250,11 @@ public:
_LIBCPP_ALWAYS_INLINE
static coroutine_handle from_promise(_Promise& __promise) _NOEXCEPT {
typedef typename remove_cv<_Promise>::type _RawPromise;
coroutine_handle __tmp;
__tmp.__handle_ = __builtin_coro_promise(_VSTD::addressof(__promise),
__alignof(_Promise), true);
__tmp.__handle_ = __builtin_coro_promise(
_VSTD::addressof(const_cast<_RawPromise&>(__promise)),
__alignof(_Promise), true);
return __tmp;
}
};

View File

@ -28,6 +28,39 @@
namespace coro = std::experimental;
struct MyCoro {
struct promise_type {
void unhandled_exception() {}
void return_void() {}
coro::suspend_never initial_suspend() { return {}; }
coro::suspend_never final_suspend() { return {}; }
MyCoro get_return_object() {
do_runtime_test();
return {};
}
void do_runtime_test() {
// Test that a coroutine_handle<const T> can be created from a const
// promise_type and that it represents the same coroutine as
// coroutine_handle<T>
using CH = coro::coroutine_handle<promise_type>;
using CCH = coro::coroutine_handle<const promise_type>;
const auto &cthis = *this;
CH h = CH::from_promise(*this);
CCH h2 = CCH::from_promise(*this);
CCH h3 = CCH::from_promise(cthis);
assert(&h.promise() == this);
assert(&h2.promise() == this);
assert(&h3.promise() == this);
assert(h.address() == h2.address());
assert(h2.address() == h3.address());
}
};
};
MyCoro do_runtime_test() {
co_await coro::suspend_never{};
}
template <class Promise>
void do_test(coro::coroutine_handle<Promise>&& H) {
@ -46,4 +79,6 @@ void do_test(coro::coroutine_handle<Promise>&& H) {
int main()
{
do_test(coro::coroutine_handle<int>{});
do_test(coro::coroutine_handle<const int>{});
do_runtime_test();
}