Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef ABSL_TYPES_INTERNAL_OPTIONAL_H_
00016 #define ABSL_TYPES_INTERNAL_OPTIONAL_H_
00017
00018 #include <functional>
00019 #include <new>
00020 #include <type_traits>
00021 #include <utility>
00022
00023 #include "absl/base/internal/inline_variable.h"
00024 #include "absl/memory/memory.h"
00025 #include "absl/meta/type_traits.h"
00026 #include "absl/utility/utility.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #if defined(__clang__)
00046 #if __has_feature(cxx_inheriting_constructors)
00047 #define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
00048 #endif
00049 #elif (defined(__GNUC__) && \
00050 (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
00051 (__cpp_inheriting_constructors >= 200802) || \
00052 (defined(_MSC_VER) && _MSC_VER >= 1910)
00053 #define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
00054 #endif
00055
00056 namespace absl {
00057
00058
00059 template <typename T>
00060 class optional;
00061
00062 namespace optional_internal {
00063
00064
00065 struct init_t {
00066 explicit init_t() = default;
00067 };
00068
00069 struct empty_struct {};
00070
00071
00072
00073
00074 template <typename T, bool unused = std::is_trivially_destructible<T>::value>
00075 class optional_data_dtor_base {
00076 struct dummy_type {
00077 static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
00078
00079 empty_struct data[sizeof(T) / sizeof(empty_struct)];
00080 };
00081
00082 protected:
00083
00084 bool engaged_;
00085
00086 union {
00087 dummy_type dummy_;
00088 T data_;
00089 };
00090
00091 void destruct() noexcept {
00092 if (engaged_) {
00093 data_.~T();
00094 engaged_ = false;
00095 }
00096 }
00097
00098
00099 constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
00100
00101 template <typename... Args>
00102 constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
00103 : engaged_(true), data_(absl::forward<Args>(args)...) {}
00104
00105 ~optional_data_dtor_base() { destruct(); }
00106 };
00107
00108
00109 template <typename T>
00110 class optional_data_dtor_base<T, true> {
00111 struct dummy_type {
00112 static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
00113
00114 empty_struct data[sizeof(T) / sizeof(empty_struct)];
00115 };
00116
00117 protected:
00118
00119 bool engaged_;
00120
00121 union {
00122 dummy_type dummy_;
00123 T data_;
00124 };
00125 void destruct() noexcept { engaged_ = false; }
00126
00127
00128 constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
00129
00130 template <typename... Args>
00131 constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
00132 : engaged_(true), data_(absl::forward<Args>(args)...) {}
00133 };
00134
00135 template <typename T>
00136 class optional_data_base : public optional_data_dtor_base<T> {
00137 protected:
00138 using base = optional_data_dtor_base<T>;
00139 #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
00140 using base::base;
00141 #else
00142 optional_data_base() = default;
00143
00144 template <typename... Args>
00145 constexpr explicit optional_data_base(in_place_t t, Args&&... args)
00146 : base(t, absl::forward<Args>(args)...) {}
00147 #endif
00148
00149 template <typename... Args>
00150 void construct(Args&&... args) {
00151
00152 ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
00153 this->engaged_ = true;
00154 }
00155
00156 template <typename U>
00157 void assign(U&& u) {
00158 if (this->engaged_) {
00159 this->data_ = std::forward<U>(u);
00160 } else {
00161 construct(std::forward<U>(u));
00162 }
00163 }
00164 };
00165
00166
00167
00168
00169
00170
00171
00172 template <typename T,
00173 bool unused = absl::is_trivially_copy_constructible<T>::value&&
00174 absl::is_trivially_copy_assignable<typename std::remove_cv<
00175 T>::type>::value&& std::is_trivially_destructible<T>::value>
00176 class optional_data;
00177
00178
00179 template <typename T>
00180 class optional_data<T, true> : public optional_data_base<T> {
00181 protected:
00182 #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
00183 using optional_data_base<T>::optional_data_base;
00184 #else
00185 optional_data() = default;
00186
00187 template <typename... Args>
00188 constexpr explicit optional_data(in_place_t t, Args&&... args)
00189 : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
00190 #endif
00191 };
00192
00193 template <typename T>
00194 class optional_data<T, false> : public optional_data_base<T> {
00195 protected:
00196 #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
00197 using optional_data_base<T>::optional_data_base;
00198 #else
00199 template <typename... Args>
00200 constexpr explicit optional_data(in_place_t t, Args&&... args)
00201 : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
00202 #endif
00203
00204 optional_data() = default;
00205
00206 optional_data(const optional_data& rhs) : optional_data_base<T>() {
00207 if (rhs.engaged_) {
00208 this->construct(rhs.data_);
00209 }
00210 }
00211
00212 optional_data(optional_data&& rhs) noexcept(
00213 absl::default_allocator_is_nothrow::value ||
00214 std::is_nothrow_move_constructible<T>::value)
00215 : optional_data_base<T>() {
00216 if (rhs.engaged_) {
00217 this->construct(std::move(rhs.data_));
00218 }
00219 }
00220
00221 optional_data& operator=(const optional_data& rhs) {
00222 if (rhs.engaged_) {
00223 this->assign(rhs.data_);
00224 } else {
00225 this->destruct();
00226 }
00227 return *this;
00228 }
00229
00230 optional_data& operator=(optional_data&& rhs) noexcept(
00231 std::is_nothrow_move_assignable<T>::value&&
00232 std::is_nothrow_move_constructible<T>::value) {
00233 if (rhs.engaged_) {
00234 this->assign(std::move(rhs.data_));
00235 } else {
00236 this->destruct();
00237 }
00238 return *this;
00239 }
00240 };
00241
00242
00243
00244 enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
00245
00246
00247 template <copy_traits>
00248 class optional_ctor_base;
00249
00250 template <>
00251 class optional_ctor_base<copy_traits::copyable> {
00252 public:
00253 constexpr optional_ctor_base() = default;
00254 optional_ctor_base(const optional_ctor_base&) = default;
00255 optional_ctor_base(optional_ctor_base&&) = default;
00256 optional_ctor_base& operator=(const optional_ctor_base&) = default;
00257 optional_ctor_base& operator=(optional_ctor_base&&) = default;
00258 };
00259
00260 template <>
00261 class optional_ctor_base<copy_traits::movable> {
00262 public:
00263 constexpr optional_ctor_base() = default;
00264 optional_ctor_base(const optional_ctor_base&) = delete;
00265 optional_ctor_base(optional_ctor_base&&) = default;
00266 optional_ctor_base& operator=(const optional_ctor_base&) = default;
00267 optional_ctor_base& operator=(optional_ctor_base&&) = default;
00268 };
00269
00270 template <>
00271 class optional_ctor_base<copy_traits::non_movable> {
00272 public:
00273 constexpr optional_ctor_base() = default;
00274 optional_ctor_base(const optional_ctor_base&) = delete;
00275 optional_ctor_base(optional_ctor_base&&) = delete;
00276 optional_ctor_base& operator=(const optional_ctor_base&) = default;
00277 optional_ctor_base& operator=(optional_ctor_base&&) = default;
00278 };
00279
00280
00281 template <copy_traits>
00282 class optional_assign_base;
00283
00284 template <>
00285 class optional_assign_base<copy_traits::copyable> {
00286 public:
00287 constexpr optional_assign_base() = default;
00288 optional_assign_base(const optional_assign_base&) = default;
00289 optional_assign_base(optional_assign_base&&) = default;
00290 optional_assign_base& operator=(const optional_assign_base&) = default;
00291 optional_assign_base& operator=(optional_assign_base&&) = default;
00292 };
00293
00294 template <>
00295 class optional_assign_base<copy_traits::movable> {
00296 public:
00297 constexpr optional_assign_base() = default;
00298 optional_assign_base(const optional_assign_base&) = default;
00299 optional_assign_base(optional_assign_base&&) = default;
00300 optional_assign_base& operator=(const optional_assign_base&) = delete;
00301 optional_assign_base& operator=(optional_assign_base&&) = default;
00302 };
00303
00304 template <>
00305 class optional_assign_base<copy_traits::non_movable> {
00306 public:
00307 constexpr optional_assign_base() = default;
00308 optional_assign_base(const optional_assign_base&) = default;
00309 optional_assign_base(optional_assign_base&&) = default;
00310 optional_assign_base& operator=(const optional_assign_base&) = delete;
00311 optional_assign_base& operator=(optional_assign_base&&) = delete;
00312 };
00313
00314 template <typename T>
00315 struct ctor_copy_traits {
00316 static constexpr copy_traits traits =
00317 std::is_copy_constructible<T>::value
00318 ? copy_traits::copyable
00319 : std::is_move_constructible<T>::value ? copy_traits::movable
00320 : copy_traits::non_movable;
00321 };
00322
00323 template <typename T>
00324 struct assign_copy_traits {
00325 static constexpr copy_traits traits =
00326 absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value
00327 ? copy_traits::copyable
00328 : absl::is_move_assignable<T>::value &&
00329 std::is_move_constructible<T>::value
00330 ? copy_traits::movable
00331 : copy_traits::non_movable;
00332 };
00333
00334
00335 template <typename T, typename U>
00336 struct is_constructible_convertible_from_optional
00337 : std::integral_constant<
00338 bool, std::is_constructible<T, optional<U>&>::value ||
00339 std::is_constructible<T, optional<U>&&>::value ||
00340 std::is_constructible<T, const optional<U>&>::value ||
00341 std::is_constructible<T, const optional<U>&&>::value ||
00342 std::is_convertible<optional<U>&, T>::value ||
00343 std::is_convertible<optional<U>&&, T>::value ||
00344 std::is_convertible<const optional<U>&, T>::value ||
00345 std::is_convertible<const optional<U>&&, T>::value> {};
00346
00347
00348 template <typename T, typename U>
00349 struct is_constructible_convertible_assignable_from_optional
00350 : std::integral_constant<
00351 bool, is_constructible_convertible_from_optional<T, U>::value ||
00352 std::is_assignable<T&, optional<U>&>::value ||
00353 std::is_assignable<T&, optional<U>&&>::value ||
00354 std::is_assignable<T&, const optional<U>&>::value ||
00355 std::is_assignable<T&, const optional<U>&&>::value> {};
00356
00357
00358
00359 bool convertible_to_bool(bool);
00360
00361
00362
00363
00364
00365 template <typename T, typename = size_t>
00366 struct optional_hash_base {
00367 optional_hash_base() = delete;
00368 optional_hash_base(const optional_hash_base&) = delete;
00369 optional_hash_base(optional_hash_base&&) = delete;
00370 optional_hash_base& operator=(const optional_hash_base&) = delete;
00371 optional_hash_base& operator=(optional_hash_base&&) = delete;
00372 };
00373
00374 template <typename T>
00375 struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
00376 std::declval<absl::remove_const_t<T> >()))> {
00377 using argument_type = absl::optional<T>;
00378 using result_type = size_t;
00379 size_t operator()(const absl::optional<T>& opt) const {
00380 absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();
00381 if (opt) {
00382 return std::hash<absl::remove_const_t<T> >()(*opt);
00383 } else {
00384 return static_cast<size_t>(0x297814aaad196e6dULL);
00385 }
00386 }
00387 };
00388
00389 }
00390 }
00391
00392 #undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
00393
00394 #endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_