diff --git a/ostd/coroutine.hh b/ostd/coroutine.hh index 7d46b5a..5faaf51 100644 --- a/ostd/coroutine.hh +++ b/ostd/coroutine.hh @@ -27,26 +27,44 @@ template struct coroutine; namespace detail { - /* like reference_wrapper but for any value */ + /* like reference_wrapper but for any value... doesn't have + * to be default constructible, so we can't store it directly + */ template struct arg_wrapper { arg_wrapper() = default; - arg_wrapper(T arg): p_arg(std::move(arg)) {} + arg_wrapper(T arg): p_init(true) { + new (&p_arg) T(std::move(arg)); + } + ~arg_wrapper() { + if (p_init) { + reinterpret_cast(&p_arg)->~T(); + } + } void operator=(T arg) { - p_arg = std::move(arg); + if (p_init) { + reinterpret_cast(&p_arg)->~T(); + } else { + p_init = true; + } + new (&p_arg) T(std::move(arg)); } operator T &&() { - return std::move(p_arg); + return std::move(*reinterpret_cast(&p_arg)); } void swap(arg_wrapper &other) { using std::swap; - swap(p_arg, other.p_arg); + swap( + *reinterpret_cast(&p_arg), + *reinterpret_cast(&other.p_arg) + ); } private: - T p_arg = T{}; + std::aligned_storage_t p_arg; + bool p_init = false; }; template