forked from OctaForge/libostd
coro args/results don't need to be default constructible
This commit is contained in:
parent
ea9ac2e5c6
commit
c89953c11f
|
@ -27,26 +27,44 @@ template<typename T>
|
||||||
struct coroutine;
|
struct coroutine;
|
||||||
|
|
||||||
namespace detail {
|
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<typename T>
|
template<typename T>
|
||||||
struct arg_wrapper {
|
struct arg_wrapper {
|
||||||
arg_wrapper() = default;
|
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<T *>(&p_arg)->~T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void operator=(T arg) {
|
void operator=(T arg) {
|
||||||
p_arg = std::move(arg);
|
if (p_init) {
|
||||||
|
reinterpret_cast<T *>(&p_arg)->~T();
|
||||||
|
} else {
|
||||||
|
p_init = true;
|
||||||
|
}
|
||||||
|
new (&p_arg) T(std::move(arg));
|
||||||
}
|
}
|
||||||
operator T &&() {
|
operator T &&() {
|
||||||
return std::move(p_arg);
|
return std::move(*reinterpret_cast<T *>(&p_arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(arg_wrapper &other) {
|
void swap(arg_wrapper &other) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p_arg, other.p_arg);
|
swap(
|
||||||
|
*reinterpret_cast<T *>(&p_arg),
|
||||||
|
*reinterpret_cast<T *>(&other.p_arg)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T p_arg = T{};
|
std::aligned_storage_t <sizeof(T), alignof(T)> p_arg;
|
||||||
|
bool p_init = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
Loading…
Reference in a new issue