1#ifndef NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
2#define NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
11#include <initializer_list>
16NEFORCE_BEGIN_NAMESPACE__
28struct optional_exception final : memory_exception {
29 explicit optional_exception(
const char* info =
"Access the Null Value of Optional.",
const char*
type = static_type,
30 const int code = 0) noexcept :
31 memory_exception(info,
type,
code) {}
33 explicit optional_exception(
const exception& e) :
34 memory_exception(e) {}
36 ~optional_exception()
override =
default;
37 static constexpr auto static_type =
"optional_exception";
72 "optional do not contains none_t and inplace_construct_tag types.");
74 static_assert(!
is_reference_v<T>,
"optional of reference type should use optional<T&> specialization.");
80 using const_pointer =
const T*;
81 using const_reference =
const T&;
89 using convertible_from_optional =
96 using assignable_from_optional =
100 bool have_value_ =
false;
103 constexpr T* get_ptr()
noexcept {
return reinterpret_cast<T*
>(&storage_); }
104 constexpr const T* get_ptr()
const noexcept {
return reinterpret_cast<const T*
>(&storage_); }
175 template <
typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional> &&
176 negation_v<conjunction<is_scalar<T>, is_same<T, decay_t<U>>>> &&
177 is_constructible_v<T, U> && is_assignable_v<T&, U>,
183 *get_ptr() = _NEFORCE
move(temp);
196 template <
typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, const U&> &&
197 is_convertible_v<const U&, T> && !convertible_from_optional<U>::value,
211 template <
typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, const U&> &&
212 !is_convertible_v<const U&, T> && !convertible_from_optional<U>::value,
227 template <
typename U = T,
253 if (other.have_value_) {
268 if (other.have_value_) {
286 template <
typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> && is_convertible_v<U, T> &&
287 !convertible_from_optional<U>::value,
301 template <
typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> && !is_convertible_v<U, T> &&
302 !convertible_from_optional<U>::value,
317 template <
typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional> && is_constructible_v<T, U> &&
318 is_assignable_v<T&, U> && !convertible_from_optional<U>::value &&
319 !assignable_from_optional<U>::value,
325 *get_ptr() = _NEFORCE
move(*other);
341 if (other.have_value_) {
358 if (other.have_value_) {
360 *get_ptr() = _NEFORCE
move(*other);
378 template <
typename U, enable_if_t<is_constructible_v<T, U&>,
int> = 0>
392 template <
typename U, enable_if_t<is_assignable_v<T&, U&>,
int> = 0>
426 template <
typename U,
typename... Types,
459 template <
typename U,
typename... Types,
461 NEFORCE_CONSTEXPR20
void
472 NEFORCE_CONSTEXPR20
void reset() noexcept {
483 NEFORCE_NODISCARD
constexpr bool has_value() const noexcept {
return have_value_; }
489 constexpr explicit operator bool() const noexcept {
return have_value_; }
496 constexpr const_reference
value() const& {
520 constexpr const value_type&&
value() const&& {
524 return _NEFORCE
move(*get_ptr());
536 return _NEFORCE
move(*get_ptr());
560 return _NEFORCE
move(*get_ptr());
569 template <
typename F, enable_if_t<is_invocable_v<F> && is_copy_constructible_v<T>,
int> = 0>
583 template <
typename F, enable_if_t<is_invocable_v<F> && is_move_constructible_v<T>,
int> = 0>
586 return _NEFORCE
move(*
this);
597 template <
typename F>
611 template <
typename F>
625 template <
typename F>
639 template <
typename F>
653 template <
typename F>
667 template <
typename F>
681 template <
typename F>
695 template <
typename F>
707 constexpr const_pointer
operator->() const noexcept {
return get_ptr(); }
713 constexpr pointer
operator->() noexcept {
return get_ptr(); }
719 constexpr const_reference
operator*() const& noexcept {
return *get_ptr(); }
725 constexpr reference
operator*() &
noexcept {
return *get_ptr(); }
731 constexpr const value_type&&
operator*() const&& noexcept {
return _NEFORCE
move(*get_ptr()); }
737 constexpr value_type&&
operator*() &&
noexcept {
return _NEFORCE
move(*get_ptr()); }
745 if (have_value_ != rhs.have_value_) {
749 return *get_ptr() == *rhs.get_ptr();
760 if (!have_value_ || !rhs.have_value_) {
763 return *get_ptr() < *rhs.get_ptr();
767 constexpr bool operator!=(none_t )
const noexcept {
return have_value_; }
768 constexpr bool operator>(none_t )
const noexcept {
return have_value_; }
769 constexpr bool operator<(none_t )
const noexcept {
return false; }
770 constexpr bool operator>=(none_t )
const noexcept {
return true; }
771 constexpr bool operator<=(none_t )
const noexcept {
return !have_value_; }
773 friend constexpr bool operator==(none_t ,
const optional& rhs)
noexcept {
return !rhs.have_value_; }
774 friend constexpr bool operator!=(none_t ,
const optional& rhs)
noexcept {
return rhs.have_value_; }
775 friend constexpr bool operator>(none_t ,
const optional& )
noexcept {
return false; }
776 friend constexpr bool operator<(none_t ,
const optional& rhs)
noexcept {
return rhs.have_value_; }
777 friend constexpr bool operator>=(none_t ,
const optional& rhs)
noexcept {
return !rhs.have_value_; }
778 friend constexpr bool operator<=(none_t ,
const optional& )
noexcept {
return true; }
784 NEFORCE_NODISCARD
constexpr size_t to_hash() const noexcept {
785 return have_value_ ?
hash<T>()(*get_ptr()) : constants::FNV_OFFSET_BASIS;
797 if (have_value_ && other.have_value_) {
798 _NEFORCE
swap(*
this, other);
799 }
else if (have_value_) {
800 other.emplace(_NEFORCE
move(**
this));
802 }
else if (other.have_value_) {
833 template <
typename U>
855 template <
typename U, enable_if_t<is_convertible_v<U&, T&>,
int> = 0>
864 template <
typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>,
int> = 0>
873 template <typename U, enable_if_t<convertible_from_optional_ref<U>::value,
int> = 0>
904 template <
typename U = T, enable_if_t<is_assignable_v<T&, U&>,
int> = 0>
916 template <
typename U, enable_if_t<is_assignable_v<T&, U&>,
int> = 0>
954 template <
typename... Types>
968 template <
typename U, enable_if_t<is_convertible_v<U&, T&>,
int> = 0>
980 template <
typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>,
int> = 0>
989 NEFORCE_CONSTEXPR20
void reset() noexcept { ptr_ =
nullptr; }
994 NEFORCE_NODISCARD
constexpr bool has_value() const noexcept {
return ptr_ !=
nullptr; }
1000 constexpr explicit operator bool() const noexcept {
return ptr_ !=
nullptr; }
1008 if (ptr_ ==
nullptr) {
1020 if (ptr_ ==
nullptr) {
1032 if (ptr_ ==
nullptr) {
1044 if (ptr_ ==
nullptr) {
1055 template <
typename U>
1068 template <
typename U>
1071 return _NEFORCE
move(*ptr_);
1082 template <
typename F, enable_if_t<is_invocable_v<F>,
int> = 0>
1096 template <
typename F, enable_if_t<is_invocable_v<F>,
int> = 0>
1099 return _NEFORCE
move(*
this);
1110 template <
typename F>
1124 template <
typename F>
1138 template <
typename F>
1152 template <
typename F>
1166 template <
typename F>
1180 template <
typename F>
1194 template <
typename F>
1208 template <
typename F>
1232 constexpr const T&
operator*() const& noexcept {
return *ptr_; }
1244 constexpr const T&&
operator*() const&& noexcept {
return *ptr_; }
1258 if (ptr_ ==
nullptr || rhs.ptr_ ==
nullptr) {
1259 return ptr_ == rhs.ptr_;
1261 return *ptr_ == *rhs.ptr_;
1269 constexpr bool less_than(
const optional& rhs)
const noexcept {
return ptr_ && rhs.ptr_ && *ptr_ < *rhs.ptr_; }
1271 constexpr bool operator==(
none_t )
const noexcept {
return ptr_ ==
nullptr; }
1272 constexpr bool operator!=(
none_t )
const noexcept {
return ptr_ !=
nullptr; }
1273 constexpr bool operator>(
none_t )
const noexcept {
return ptr_ !=
nullptr; }
1274 constexpr bool operator<(
none_t )
const noexcept {
return false; }
1275 constexpr bool operator>=(
none_t )
const noexcept {
return true; }
1276 constexpr bool operator<=(
none_t )
const noexcept {
return ptr_ ==
nullptr; }
1280 friend constexpr bool operator>(
none_t ,
const optional& )
noexcept {
return false; }
1281 friend constexpr bool operator<(
none_t ,
const optional& rhs)
noexcept {
return rhs.ptr_ !=
nullptr; }
1282 friend constexpr bool operator>=(
none_t ,
const optional& rhs)
noexcept {
return rhs.ptr_ ==
nullptr; }
1283 friend constexpr bool operator<=(
none_t ,
const optional& )
noexcept {
return true; }
1289 NEFORCE_NODISCARD
constexpr size_t to_hash() const noexcept {
1300#ifdef NEFORCE_STANDARD_17
1301template <
typename T>
1327template <
typename T,
typename U,
typename... Args>
1342template <
typename T>
1344 return static_cast<const T&
>(
static_cast<const optional<T>&
>(opt).
value());
1354template <
typename T>
1366template <
typename T>
1368 return static_cast<const T&&
>(
static_cast<const optional<T>&&
>(opt).
value());
1378template <
typename T>
1385NEFORCE_END_NAMESPACE__
constexpr void swap(optional &other) noexcept
交换两个可选值
constexpr T & emplace(U &value) noexcept
隐式转换原位构造引用
constexpr optional & operator=(const optional &other) noexcept=default
复制赋值运算符
constexpr optional & operator=(const optional< U & > &other)
从引用可选值赋值(重新绑定)
constexpr bool less_than(const optional &rhs) const noexcept
小于比较运算符
constexpr const T & operator*() const &noexcept
常量左值解引用运算符
constexpr T && operator*() &&noexcept
右值解引用运算符
const T & const_reference
常量引用类型
constexpr bool has_value() const noexcept
检查是否持有引用
constexpr auto transform(F &&f) &-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
左值转换操作
constexpr T value_or(U &&value) &&
取出存储的引用的移动值
constexpr auto transform(F &&f) const &&-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
常量右值转换操作
constexpr optional(const _NEFORCE optional< U & > &other) noexcept
从引用可选值隐式转换复制构造
constexpr T * operator->() noexcept
箭头运算符
constexpr size_t to_hash() const noexcept
计算哈希值
constexpr optional(U &value) noexcept
从可转换引用隐式转换构造
constexpr T value_or(U &&value) const &
取出存储的引用的拷贝值
constexpr const T * operator->() const noexcept
常量箭头运算符
constexpr optional & operator=(none_t n) noexcept
空值赋值运算符
constexpr T & value() &
获取左值引用
constexpr optional(optional &&other) noexcept
移动构造函数
constexpr optional(T &value) noexcept
从引用构造
constexpr const T && value() const &&
获取常量右值引用
constexpr optional(const optional &other) noexcept=default
复制构造函数
constexpr const T & value() const &
获取常量左值引用
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
constexpr void reset() noexcept
重置引用
const T * const_pointer
常量指针类型
constexpr optional & operator=(optional &&other) noexcept
移动赋值运算符
constexpr bool equal_to(const optional &rhs) const noexcept
等于比较运算符
constexpr auto transform(F &&f) &&-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
右值转换操作
constexpr optional(none_t n=none) noexcept
默认构造函数
constexpr optional or_else(F &&f) &&
右值否则操作
constexpr T && value() &&
获取右值引用
constexpr decltype(auto) and_then(F &&f) const &
常量左值然后操作
constexpr const T && operator*() const &&noexcept
常量右值解引用运算符
constexpr auto transform(F &&f) const &-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
常量左值转换操作
constexpr T & operator*() &noexcept
左值解引用运算符
constexpr decltype(auto) and_then(F &&f) &
左值然后操作
constexpr decltype(auto) and_then(F &&f) const &&
常量右值然后操作
constexpr optional or_else(F &&f) const &
常量左值否则操作
constexpr optional & operator=(U &value)
从引用赋值(重新绑定)
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
constexpr auto transform(F &&f) const &&-> optional< remove_cvref_t< decltype(f(_NEFORCE move(*get_ptr())))> >
右值转换操作
constexpr optional & operator=(none_t n) noexcept
空值赋值运算符
constexpr value_type && operator*() &&noexcept
右值解引用运算符
constexpr value_type value_or(value_type value) const &noexcept(is_nothrow_copy_constructible_v< value_type >)
取出存储的值的拷贝值
constexpr optional(inplace_construct_tag, std::initializer_list< U > ilist, Types &&... args) noexcept(is_nothrow_constructible_v< T, std::initializer_list< U > &, Types... >)
使用初始化列表原位构造
constexpr auto transform(F &&f) &-> optional< remove_cvref_t< decltype(f(*get_ptr()))> >
左值转换操作
constexpr void emplace(Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造值
constexpr void swap(optional &other) noexcept(is_nothrow_move_constructible_v< T > &&is_nothrow_swappable_v< T >)
交换两个可选值
constexpr const_reference operator*() const &noexcept
常量左值解引用运算符
constexpr decltype(auto) and_then(F &&f) const &
常量左值然后操作
constexpr optional(const optional< U & > &other)
从引用可选值赋值
constexpr optional(const T &value) noexcept(is_nothrow_copy_constructible_v< T >)
从值拷贝构造
constexpr optional(U &&value) noexcept(is_nothrow_constructible_v< T, U >)
从值隐式转换构造
constexpr const value_type && operator*() const &&noexcept
常量右值解引用运算符
optional(const optional &other)
复制构造函数
constexpr ~optional() noexcept
析构函数
constexpr optional(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U >)
从可选值隐式转换移动构造
constexpr reference operator*() &noexcept
左值解引用运算符
constexpr auto transform(F &&f) &&-> optional< remove_cvref_t< decltype(f(_NEFORCE move(*get_ptr())))> >
常量右值转换操作
constexpr size_t to_hash() const noexcept
计算哈希值
constexpr void reset() noexcept
重置可选值为空
optional & operator=(optional &&other) noexcept
移动赋值运算符
constexpr optional(const optional< U > &other) noexcept(is_nothrow_constructible_v< T, const U & >)
从可选值隐式转换复制构造
constexpr auto transform(F &&f) const &-> optional< remove_cvref_t< decltype(f(*get_ptr()))> >
常量左值转换操作
constexpr void emplace(std::initializer_list< U > ilist, Types &&... args) noexcept(is_nothrow_constructible_v< T, std::initializer_list< U > &, Types... >)
使用初始化列表原位构造值
constexpr value_type value_or(value_type value) &&noexcept(is_nothrow_move_constructible_v< value_type >)
取出存储的值的移出值
optional & operator=(const optional &other)
复制赋值运算符
constexpr optional or_else(F &&f) const &
常量左值否则操作
constexpr value_type && value() &&
取出存储的值
constexpr optional & operator=(const optional< U > &other) noexcept(is_nothrow_constructible_v< T, const U & > &&is_nothrow_assignable_v< T &, const U & >)
从可选值复制赋值
constexpr const_pointer operator->() const noexcept
常量箭头运算符
constexpr optional or_else(F &&f) &&
右值否则操作
constexpr optional(inplace_construct_tag, Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造
constexpr decltype(auto) and_then(F &&f) &
左值然后操作
constexpr optional & operator=(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U > &&is_nothrow_assignable_v< T &, U >)
从可选值移动赋值
constexpr optional & operator=(const optional< U & > &other)
从引用可选值赋值
constexpr bool equal_to(const optional &rhs) const noexcept
等于比较运算符
constexpr decltype(auto) and_then(F &&f) const &&
常量右值然后操作
constexpr optional(none_t n=none) noexcept
从空值构造
constexpr optional(T &&value) noexcept(is_nothrow_move_constructible_v< T >)
从值移动构造
constexpr const_reference value() const &
取出存储的值
constexpr bool has_value() const noexcept
检查是否包含值
constexpr pointer operator->() noexcept
箭头运算符
constexpr const value_type && value() const &&
取出存储的值
constexpr optional & operator=(U &&value) noexcept(is_nothrow_constructible_v< T, U > &&is_nothrow_assignable_v< T &, U >)
从值赋值
constexpr reference value() &
取出存储的值
optional(optional &&other) noexcept
移动构造函数
constexpr bool less_than(const optional &rhs) const noexcept
小于比较运算符
typename aligned_storage< Len, Align >::type aligned_storage_t
aligned_storage的便捷别名
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr bool is_object_v
is_object的便捷变量模板
constexpr bool is_reference_v
is_reference的便捷变量模板
constexpr bool is_array_v
is_array的便捷变量模板
constexpr bool is_convertible_v
is_convertible的便捷变量模板
bool operator!=(const function< Res(Args...)> &f, nullptr_t np) noexcept
不等于空指针比较
bool operator==(const function< Res(Args...)> &f, nullptr_t np) noexcept
等于空指针比较
constexpr void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
constexpr T * construct(T *ptr, Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
在指定内存位置构造对象
constexpr none_t none
默认空表示
constexpr optional< T > make_optional(Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
原位构造可选值
constexpr const T & get(const optional< T > &opt)
获取可选值中的值
typename remove_cvref< T >::type remove_cvref_t
remove_cvref的便捷别名
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
void swap()=delete
删除无参数的swap重载
constexpr bool is_nothrow_swappable_v
is_nothrow_swappable的便捷变量模板
constexpr bool is_constructible_v
is_constructible的便捷变量模板
constexpr bool is_nothrow_copy_constructible_v
is_nothrow_copy_constructible的便捷变量模板
constexpr bool is_nothrow_move_constructible_v
is_nothrow_move_constructible的便捷变量模板
constexpr bool is_assignable_v
is_assignable的便捷变量模板
constexpr bool is_nothrow_constructible_v
is_nothrow_constructible的便捷变量模板
constexpr bool is_nothrow_assignable_v
is_nothrow_assignable的便捷变量模板
constexpr bool is_any_of_v
is_any_of的便捷变量模板
bool_constant< true > true_type
表示true的类型
constexpr bool is_same_v
is_same的便捷变量模板
bool_constant< false > false_type
表示false的类型
integral_constant< bool, Value > bool_constant
布尔常量包装器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
exception(const char *info=static_type, const char *type=static_type, const int code=0)
构造函数
const char * type() const noexcept
获取异常类型
int code() const noexcept
获取异常码
static constexpr bool value