File indexing completed on 2025-01-30 09:31:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_TYPES_INTERNAL_OPTIONAL_H_
0016 #define ABSL_TYPES_INTERNAL_OPTIONAL_H_
0017
0018 #include <functional>
0019 #include <new>
0020 #include <type_traits>
0021 #include <utility>
0022
0023 #include "absl/base/internal/inline_variable.h"
0024 #include "absl/memory/memory.h"
0025 #include "absl/meta/type_traits.h"
0026 #include "absl/utility/utility.h"
0027
0028 namespace absl {
0029 ABSL_NAMESPACE_BEGIN
0030
0031
0032 template <typename T>
0033 class optional;
0034
0035 namespace optional_internal {
0036
0037
0038 struct init_t {
0039 explicit init_t() = default;
0040 };
0041
0042 struct empty_struct {};
0043
0044
0045
0046
0047 template <typename T, bool unused = std::is_trivially_destructible<T>::value>
0048 class optional_data_dtor_base {
0049 struct dummy_type {
0050 static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
0051
0052 empty_struct data[sizeof(T) / sizeof(empty_struct)];
0053 };
0054
0055 protected:
0056
0057 bool engaged_;
0058
0059 union {
0060 T data_;
0061 dummy_type dummy_;
0062 };
0063
0064 void destruct() noexcept {
0065 if (engaged_) {
0066
0067 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
0068 #pragma GCC diagnostic push
0069 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0070 #endif
0071 data_.~T();
0072 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
0073 #pragma GCC diagnostic pop
0074 #endif
0075 engaged_ = false;
0076 }
0077 }
0078
0079
0080 constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
0081
0082 template <typename... Args>
0083 constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
0084 : engaged_(true), data_(std::forward<Args>(args)...) {}
0085
0086 ~optional_data_dtor_base() { destruct(); }
0087 };
0088
0089
0090 template <typename T>
0091 class optional_data_dtor_base<T, true> {
0092 struct dummy_type {
0093 static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
0094
0095 empty_struct data[sizeof(T) / sizeof(empty_struct)];
0096 };
0097
0098 protected:
0099
0100 bool engaged_;
0101
0102 union {
0103 T data_;
0104 dummy_type dummy_;
0105 };
0106 void destruct() noexcept { engaged_ = false; }
0107
0108
0109 constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
0110
0111 template <typename... Args>
0112 constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
0113 : engaged_(true), data_(std::forward<Args>(args)...) {}
0114 };
0115
0116 template <typename T>
0117 class optional_data_base : public optional_data_dtor_base<T> {
0118 protected:
0119 using base = optional_data_dtor_base<T>;
0120 using base::base;
0121
0122 template <typename... Args>
0123 void construct(Args&&... args) {
0124
0125 ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
0126 this->engaged_ = true;
0127 }
0128
0129 template <typename U>
0130 void assign(U&& u) {
0131 if (this->engaged_) {
0132 this->data_ = std::forward<U>(u);
0133 } else {
0134 construct(std::forward<U>(u));
0135 }
0136 }
0137 };
0138
0139
0140
0141
0142
0143
0144
0145 template <typename T,
0146 bool unused = absl::is_trivially_copy_constructible<T>::value&&
0147 absl::is_trivially_copy_assignable<typename std::remove_cv<
0148 T>::type>::value&& std::is_trivially_destructible<T>::value>
0149 class optional_data;
0150
0151
0152 template <typename T>
0153 class optional_data<T, true> : public optional_data_base<T> {
0154 protected:
0155 using optional_data_base<T>::optional_data_base;
0156 };
0157
0158 template <typename T>
0159 class optional_data<T, false> : public optional_data_base<T> {
0160 protected:
0161 using optional_data_base<T>::optional_data_base;
0162
0163 optional_data() = default;
0164
0165 optional_data(const optional_data& rhs) : optional_data_base<T>() {
0166 if (rhs.engaged_) {
0167 this->construct(rhs.data_);
0168 }
0169 }
0170
0171 optional_data(optional_data&& rhs) noexcept(
0172 absl::default_allocator_is_nothrow::value ||
0173 std::is_nothrow_move_constructible<T>::value)
0174 : optional_data_base<T>() {
0175 if (rhs.engaged_) {
0176 this->construct(std::move(rhs.data_));
0177 }
0178 }
0179
0180 optional_data& operator=(const optional_data& rhs) {
0181 if (rhs.engaged_) {
0182 this->assign(rhs.data_);
0183 } else {
0184 this->destruct();
0185 }
0186 return *this;
0187 }
0188
0189 optional_data& operator=(optional_data&& rhs) noexcept(
0190 std::is_nothrow_move_assignable<T>::value&&
0191 std::is_nothrow_move_constructible<T>::value) {
0192 if (rhs.engaged_) {
0193 this->assign(std::move(rhs.data_));
0194 } else {
0195 this->destruct();
0196 }
0197 return *this;
0198 }
0199 };
0200
0201
0202
0203 enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
0204
0205
0206 template <copy_traits>
0207 class optional_ctor_base;
0208
0209 template <>
0210 class optional_ctor_base<copy_traits::copyable> {
0211 public:
0212 constexpr optional_ctor_base() = default;
0213 optional_ctor_base(const optional_ctor_base&) = default;
0214 optional_ctor_base(optional_ctor_base&&) = default;
0215 optional_ctor_base& operator=(const optional_ctor_base&) = default;
0216 optional_ctor_base& operator=(optional_ctor_base&&) = default;
0217 };
0218
0219 template <>
0220 class optional_ctor_base<copy_traits::movable> {
0221 public:
0222 constexpr optional_ctor_base() = default;
0223 optional_ctor_base(const optional_ctor_base&) = delete;
0224 optional_ctor_base(optional_ctor_base&&) = default;
0225 optional_ctor_base& operator=(const optional_ctor_base&) = default;
0226 optional_ctor_base& operator=(optional_ctor_base&&) = default;
0227 };
0228
0229 template <>
0230 class optional_ctor_base<copy_traits::non_movable> {
0231 public:
0232 constexpr optional_ctor_base() = default;
0233 optional_ctor_base(const optional_ctor_base&) = delete;
0234 optional_ctor_base(optional_ctor_base&&) = delete;
0235 optional_ctor_base& operator=(const optional_ctor_base&) = default;
0236 optional_ctor_base& operator=(optional_ctor_base&&) = default;
0237 };
0238
0239
0240 template <copy_traits>
0241 class optional_assign_base;
0242
0243 template <>
0244 class optional_assign_base<copy_traits::copyable> {
0245 public:
0246 constexpr optional_assign_base() = default;
0247 optional_assign_base(const optional_assign_base&) = default;
0248 optional_assign_base(optional_assign_base&&) = default;
0249 optional_assign_base& operator=(const optional_assign_base&) = default;
0250 optional_assign_base& operator=(optional_assign_base&&) = default;
0251 };
0252
0253 template <>
0254 class optional_assign_base<copy_traits::movable> {
0255 public:
0256 constexpr optional_assign_base() = default;
0257 optional_assign_base(const optional_assign_base&) = default;
0258 optional_assign_base(optional_assign_base&&) = default;
0259 optional_assign_base& operator=(const optional_assign_base&) = delete;
0260 optional_assign_base& operator=(optional_assign_base&&) = default;
0261 };
0262
0263 template <>
0264 class optional_assign_base<copy_traits::non_movable> {
0265 public:
0266 constexpr optional_assign_base() = default;
0267 optional_assign_base(const optional_assign_base&) = default;
0268 optional_assign_base(optional_assign_base&&) = default;
0269 optional_assign_base& operator=(const optional_assign_base&) = delete;
0270 optional_assign_base& operator=(optional_assign_base&&) = delete;
0271 };
0272
0273 template <typename T>
0274 struct ctor_copy_traits {
0275 static constexpr copy_traits traits =
0276 std::is_copy_constructible<T>::value
0277 ? copy_traits::copyable
0278 : std::is_move_constructible<T>::value ? copy_traits::movable
0279 : copy_traits::non_movable;
0280 };
0281
0282 template <typename T>
0283 struct assign_copy_traits {
0284 static constexpr copy_traits traits =
0285 absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value
0286 ? copy_traits::copyable
0287 : absl::is_move_assignable<T>::value &&
0288 std::is_move_constructible<T>::value
0289 ? copy_traits::movable
0290 : copy_traits::non_movable;
0291 };
0292
0293
0294 template <typename T, typename U>
0295 struct is_constructible_convertible_from_optional
0296 : std::integral_constant<
0297 bool, std::is_constructible<T, optional<U>&>::value ||
0298 std::is_constructible<T, optional<U>&&>::value ||
0299 std::is_constructible<T, const optional<U>&>::value ||
0300 std::is_constructible<T, const optional<U>&&>::value ||
0301 std::is_convertible<optional<U>&, T>::value ||
0302 std::is_convertible<optional<U>&&, T>::value ||
0303 std::is_convertible<const optional<U>&, T>::value ||
0304 std::is_convertible<const optional<U>&&, T>::value> {};
0305
0306
0307 template <typename T, typename U>
0308 struct is_constructible_convertible_assignable_from_optional
0309 : std::integral_constant<
0310 bool, is_constructible_convertible_from_optional<T, U>::value ||
0311 std::is_assignable<T&, optional<U>&>::value ||
0312 std::is_assignable<T&, optional<U>&&>::value ||
0313 std::is_assignable<T&, const optional<U>&>::value ||
0314 std::is_assignable<T&, const optional<U>&&>::value> {};
0315
0316
0317
0318 bool convertible_to_bool(bool);
0319
0320
0321
0322
0323
0324 template <typename T, typename = size_t>
0325 struct optional_hash_base {
0326 optional_hash_base() = delete;
0327 optional_hash_base(const optional_hash_base&) = delete;
0328 optional_hash_base(optional_hash_base&&) = delete;
0329 optional_hash_base& operator=(const optional_hash_base&) = delete;
0330 optional_hash_base& operator=(optional_hash_base&&) = delete;
0331 };
0332
0333 template <typename T>
0334 struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
0335 std::declval<absl::remove_const_t<T> >()))> {
0336 using argument_type = absl::optional<T>;
0337 using result_type = size_t;
0338 size_t operator()(const absl::optional<T>& opt) const {
0339 absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();
0340 if (opt) {
0341 return std::hash<absl::remove_const_t<T> >()(*opt);
0342 } else {
0343 return static_cast<size_t>(0x297814aaad196e6dULL);
0344 }
0345 }
0346 };
0347
0348 }
0349 ABSL_NAMESPACE_END
0350 }
0351
0352 #endif