optional.h
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
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 // ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
00029 //
00030 // Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.
00031 // __cpp_inheriting_constructors is a predefined macro and a recommended way to
00032 // check for this language feature, but GCC doesn't support it until 5.0 and
00033 // Clang doesn't support it until 3.6.
00034 // Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template
00035 // constructor. For example, the following code won't work on MSVC 2015 Update3:
00036 // struct Base {
00037 //   int t;
00038 //   template <typename T>
00039 //   constexpr Base(T t_) : t(t_) {}
00040 // };
00041 // struct Foo : Base {
00042 //   using Base::Base;
00043 // }
00044 // constexpr Foo foo(0);  // doesn't work on MSVC 2015
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 // Forward declaration
00059 template <typename T>
00060 class optional;
00061 
00062 namespace optional_internal {
00063 
00064 // This tag type is used as a constructor parameter type for `nullopt_t`.
00065 struct init_t {
00066   explicit init_t() = default;
00067 };
00068 
00069 struct empty_struct {};
00070 
00071 // This class stores the data in optional<T>.
00072 // It is specialized based on whether T is trivially destructible.
00073 // This is the specialization for non trivially destructible type.
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     // Use an array to avoid GCC 6 placement-new warning.
00079     empty_struct data[sizeof(T) / sizeof(empty_struct)];
00080   };
00081 
00082  protected:
00083   // Whether there is data or not.
00084   bool engaged_;
00085   // Data storage
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   // dummy_ must be initialized for constexpr constructor.
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 // Specialization for trivially destructible type.
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     // Use array to avoid GCC 6 placement-new warning.
00114     empty_struct data[sizeof(T) / sizeof(empty_struct)];
00115   };
00116 
00117  protected:
00118   // Whether there is data or not.
00119   bool engaged_;
00120   // Data storage
00121   union {
00122     dummy_type dummy_;
00123     T data_;
00124   };
00125   void destruct() noexcept { engaged_ = false; }
00126 
00127   // dummy_ must be initialized for constexpr constructor.
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     // Use dummy_'s address to work around casting cv-qualified T* to void*.
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 // TODO(absl-team): Add another class using
00167 // std::is_trivially_move_constructible trait when available to match
00168 // http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that
00169 // have trivial move but nontrivial copy.
00170 // Also, we should be checking is_trivially_copyable here, which is not
00171 // supported now, so we use is_trivially_* traits instead.
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 // Trivially copyable types
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 // Ordered by level of restriction, from low to high.
00243 // Copyable implies movable.
00244 enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
00245 
00246 // Base class for enabling/disabling copy/move constructor.
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 // Base class for enabling/disabling copy/move assignment.
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 // Whether T is constructible or convertible from optional<U>.
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 // Whether T is constructible or convertible or assignable from optional<U>.
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 // Helper function used by [optional.relops], [optional.comp_with_t],
00358 // for checking whether an expression is convertible to bool.
00359 bool convertible_to_bool(bool);
00360 
00361 // Base class for std::hash<absl::optional<T>>:
00362 // If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
00363 // compute the hash; Otherwise, it is disabled.
00364 // Reference N4659 23.14.15 [unord.hash].
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 }  // namespace optional_internal
00390 }  // namespace absl
00391 
00392 #undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
00393 
00394 #endif  // ABSL_TYPES_INTERNAL_OPTIONAL_H_


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15