mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
9a5a13854d
* Add ctl utility.h Implements forward, move, swap, and declval. This commit also adds a def for nullptr_t to cxx.inc. We need it now because the CTL headers stopped including anything from libc++, so we no longer get their basic types. * Use ctl::swap in string The STL spec says that swap is located in the string_view header anyawy. Performance-wise this is a noop, but it’s slightly cleaner.
141 lines
2.7 KiB
C++
141 lines
2.7 KiB
C++
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
|
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
|
|
#define COSMOPOLITAN_CTL_OPTIONAL_H_
|
|
#include "new.h"
|
|
#include "utility.h"
|
|
|
|
namespace ctl {
|
|
|
|
template<typename T>
|
|
class optional
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
|
|
~optional()
|
|
{
|
|
if (present_)
|
|
value_.~T();
|
|
}
|
|
|
|
optional() noexcept : present_(false)
|
|
{
|
|
}
|
|
|
|
optional(const T& value) : present_(true)
|
|
{
|
|
new (&value_) T(value);
|
|
}
|
|
|
|
optional(T&& value) : present_(true)
|
|
{
|
|
new (&value_) T(ctl::move(value));
|
|
}
|
|
|
|
optional(const optional& other) : present_(other.present_)
|
|
{
|
|
if (other.present_)
|
|
new (&value_) T(other.value_);
|
|
}
|
|
|
|
optional(optional&& other) noexcept : present_(other.present_)
|
|
{
|
|
if (other.present_)
|
|
new (&value_) T(ctl::move(other.value_));
|
|
}
|
|
|
|
optional& operator=(const optional& other)
|
|
{
|
|
if (this != &other) {
|
|
reset();
|
|
if (other.present_)
|
|
new (&value_) T(other.value_);
|
|
present_ = other.present_;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
optional& operator=(optional&& other) noexcept
|
|
{
|
|
if (this != &other) {
|
|
reset();
|
|
if (other.present_)
|
|
new (&value_) T(ctl::move(other.value_));
|
|
present_ = other.present_;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
T& value() &
|
|
{
|
|
if (!present_)
|
|
__builtin_trap();
|
|
return value_;
|
|
}
|
|
|
|
const T& value() const&
|
|
{
|
|
if (!present_)
|
|
__builtin_trap();
|
|
return value_;
|
|
}
|
|
|
|
T&& value() &&
|
|
{
|
|
if (!present_)
|
|
__builtin_trap();
|
|
return ctl::move(value_);
|
|
}
|
|
|
|
explicit operator bool() const noexcept
|
|
{
|
|
return present_;
|
|
}
|
|
|
|
bool has_value() const noexcept
|
|
{
|
|
return present_;
|
|
}
|
|
|
|
void reset() noexcept
|
|
{
|
|
if (present_) {
|
|
value_.~T();
|
|
present_ = false;
|
|
}
|
|
}
|
|
|
|
template<typename... Args>
|
|
void emplace(Args&&... args)
|
|
{
|
|
reset();
|
|
present_ = true;
|
|
new (&value_) T(ctl::forward<Args>(args)...);
|
|
}
|
|
|
|
void swap(optional& other) noexcept
|
|
{
|
|
using ctl::swap;
|
|
if (present_ && other.present_) {
|
|
swap(value_, other.value_);
|
|
} else if (present_) {
|
|
other.emplace(ctl::move(value_));
|
|
reset();
|
|
} else if (other.present_) {
|
|
emplace(ctl::move(other.value_));
|
|
other.reset();
|
|
}
|
|
}
|
|
|
|
private:
|
|
union
|
|
{
|
|
T value_;
|
|
};
|
|
bool present_;
|
|
};
|
|
|
|
} // namespace ctl
|
|
|
|
#endif // COSMOPOLITAN_CTL_OPTIONAL_H_
|