| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 | // Copyright 2017 The Abseil Authors.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at////      https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.//#ifndef ABSL_TYPES_INTERNAL_OPTIONAL_H_#define ABSL_TYPES_INTERNAL_OPTIONAL_H_#include <functional>#include <new>#include <type_traits>#include <utility>#include "absl/base/internal/inline_variable.h"#include "absl/memory/memory.h"#include "absl/meta/type_traits.h"#include "absl/utility/utility.h"// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS//// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.// __cpp_inheriting_constructors is a predefined macro and a recommended way to// check for this language feature, but GCC doesn't support it until 5.0 and// Clang doesn't support it until 3.6.// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template// constructor. For example, the following code won't work on MSVC 2015 Update3:// struct Base {//   int t;//   template <typename T>//   constexpr Base(T t_) : t(t_) {}// };// struct Foo : Base {//   using Base::Base;// }// constexpr Foo foo(0);  // doesn't work on MSVC 2015#if defined(__clang__)#if __has_feature(cxx_inheriting_constructors)#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1#endif#elif (defined(__GNUC__) &&                                       \       (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \    (__cpp_inheriting_constructors >= 200802) ||                  \    (defined(_MSC_VER) && _MSC_VER >= 1910)#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1#endifnamespace absl {ABSL_NAMESPACE_BEGIN// Forward declarationtemplate <typename T>class optional;namespace optional_internal {// This tag type is used as a constructor parameter type for `nullopt_t`.struct init_t {  explicit init_t() = default;};struct empty_struct {};// This class stores the data in optional<T>.// It is specialized based on whether T is trivially destructible.// This is the specialization for non trivially destructible type.template <typename T, bool unused = std::is_trivially_destructible<T>::value>class optional_data_dtor_base {  struct dummy_type {    static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");    // Use an array to avoid GCC 6 placement-new warning.    empty_struct data[sizeof(T) / sizeof(empty_struct)];  }; protected:  // Whether there is data or not.  bool engaged_;  // Data storage  union {    T data_;    dummy_type dummy_;  };  void destruct() noexcept {    if (engaged_) {      data_.~T();      engaged_ = false;    }  }  // dummy_ must be initialized for constexpr constructor.  constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}  template <typename... Args>  constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)      : engaged_(true), data_(absl::forward<Args>(args)...) {}  ~optional_data_dtor_base() { destruct(); }};// Specialization for trivially destructible type.template <typename T>class optional_data_dtor_base<T, true> {  struct dummy_type {    static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");    // Use array to avoid GCC 6 placement-new warning.    empty_struct data[sizeof(T) / sizeof(empty_struct)];  }; protected:  // Whether there is data or not.  bool engaged_;  // Data storage  union {    T data_;    dummy_type dummy_;  };  void destruct() noexcept { engaged_ = false; }  // dummy_ must be initialized for constexpr constructor.  constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}  template <typename... Args>  constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)      : engaged_(true), data_(absl::forward<Args>(args)...) {}};template <typename T>class optional_data_base : public optional_data_dtor_base<T> { protected:  using base = optional_data_dtor_base<T>;#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS  using base::base;#else  optional_data_base() = default;  template <typename... Args>  constexpr explicit optional_data_base(in_place_t t, Args&&... args)      : base(t, absl::forward<Args>(args)...) {}#endif  template <typename... Args>  void construct(Args&&... args) {    // Use dummy_'s address to work around casting cv-qualified T* to void*.    ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);    this->engaged_ = true;  }  template <typename U>  void assign(U&& u) {    if (this->engaged_) {      this->data_ = std::forward<U>(u);    } else {      construct(std::forward<U>(u));    }  }};// TODO(absl-team): Add another class using// std::is_trivially_move_constructible trait when available to match// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that// have trivial move but nontrivial copy.// Also, we should be checking is_trivially_copyable here, which is not// supported now, so we use is_trivially_* traits instead.template <typename T,          bool unused = absl::is_trivially_copy_constructible<T>::value&&              absl::is_trivially_copy_assignable<typename std::remove_cv<                  T>::type>::value&& std::is_trivially_destructible<T>::value>class optional_data;// Trivially copyable typestemplate <typename T>class optional_data<T, true> : public optional_data_base<T> { protected:#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS  using optional_data_base<T>::optional_data_base;#else  optional_data() = default;  template <typename... Args>  constexpr explicit optional_data(in_place_t t, Args&&... args)      : optional_data_base<T>(t, absl::forward<Args>(args)...) {}#endif};template <typename T>class optional_data<T, false> : public optional_data_base<T> { protected:#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS  using optional_data_base<T>::optional_data_base;#else  template <typename... Args>  constexpr explicit optional_data(in_place_t t, Args&&... args)      : optional_data_base<T>(t, absl::forward<Args>(args)...) {}#endif  optional_data() = default;  optional_data(const optional_data& rhs) : optional_data_base<T>() {    if (rhs.engaged_) {      this->construct(rhs.data_);    }  }  optional_data(optional_data&& rhs) noexcept(      absl::default_allocator_is_nothrow::value ||      std::is_nothrow_move_constructible<T>::value)      : optional_data_base<T>() {    if (rhs.engaged_) {      this->construct(std::move(rhs.data_));    }  }  optional_data& operator=(const optional_data& rhs) {    if (rhs.engaged_) {      this->assign(rhs.data_);    } else {      this->destruct();    }    return *this;  }  optional_data& operator=(optional_data&& rhs) noexcept(      std::is_nothrow_move_assignable<T>::value&&          std::is_nothrow_move_constructible<T>::value) {    if (rhs.engaged_) {      this->assign(std::move(rhs.data_));    } else {      this->destruct();    }    return *this;  }};// Ordered by level of restriction, from low to high.// Copyable implies movable.enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };// Base class for enabling/disabling copy/move constructor.template <copy_traits>class optional_ctor_base;template <>class optional_ctor_base<copy_traits::copyable> { public:  constexpr optional_ctor_base() = default;  optional_ctor_base(const optional_ctor_base&) = default;  optional_ctor_base(optional_ctor_base&&) = default;  optional_ctor_base& operator=(const optional_ctor_base&) = default;  optional_ctor_base& operator=(optional_ctor_base&&) = default;};template <>class optional_ctor_base<copy_traits::movable> { public:  constexpr optional_ctor_base() = default;  optional_ctor_base(const optional_ctor_base&) = delete;  optional_ctor_base(optional_ctor_base&&) = default;  optional_ctor_base& operator=(const optional_ctor_base&) = default;  optional_ctor_base& operator=(optional_ctor_base&&) = default;};template <>class optional_ctor_base<copy_traits::non_movable> { public:  constexpr optional_ctor_base() = default;  optional_ctor_base(const optional_ctor_base&) = delete;  optional_ctor_base(optional_ctor_base&&) = delete;  optional_ctor_base& operator=(const optional_ctor_base&) = default;  optional_ctor_base& operator=(optional_ctor_base&&) = default;};// Base class for enabling/disabling copy/move assignment.template <copy_traits>class optional_assign_base;template <>class optional_assign_base<copy_traits::copyable> { public:  constexpr optional_assign_base() = default;  optional_assign_base(const optional_assign_base&) = default;  optional_assign_base(optional_assign_base&&) = default;  optional_assign_base& operator=(const optional_assign_base&) = default;  optional_assign_base& operator=(optional_assign_base&&) = default;};template <>class optional_assign_base<copy_traits::movable> { public:  constexpr optional_assign_base() = default;  optional_assign_base(const optional_assign_base&) = default;  optional_assign_base(optional_assign_base&&) = default;  optional_assign_base& operator=(const optional_assign_base&) = delete;  optional_assign_base& operator=(optional_assign_base&&) = default;};template <>class optional_assign_base<copy_traits::non_movable> { public:  constexpr optional_assign_base() = default;  optional_assign_base(const optional_assign_base&) = default;  optional_assign_base(optional_assign_base&&) = default;  optional_assign_base& operator=(const optional_assign_base&) = delete;  optional_assign_base& operator=(optional_assign_base&&) = delete;};template <typename T>struct ctor_copy_traits {  static constexpr copy_traits traits =      std::is_copy_constructible<T>::value          ? copy_traits::copyable          : std::is_move_constructible<T>::value ? copy_traits::movable                                                 : copy_traits::non_movable;};template <typename T>struct assign_copy_traits {  static constexpr copy_traits traits =      absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value          ? copy_traits::copyable          : absl::is_move_assignable<T>::value &&                    std::is_move_constructible<T>::value                ? copy_traits::movable                : copy_traits::non_movable;};// Whether T is constructible or convertible from optional<U>.template <typename T, typename U>struct is_constructible_convertible_from_optional    : std::integral_constant<          bool, std::is_constructible<T, optional<U>&>::value ||                    std::is_constructible<T, optional<U>&&>::value ||                    std::is_constructible<T, const optional<U>&>::value ||                    std::is_constructible<T, const optional<U>&&>::value ||                    std::is_convertible<optional<U>&, T>::value ||                    std::is_convertible<optional<U>&&, T>::value ||                    std::is_convertible<const optional<U>&, T>::value ||                    std::is_convertible<const optional<U>&&, T>::value> {};// Whether T is constructible or convertible or assignable from optional<U>.template <typename T, typename U>struct is_constructible_convertible_assignable_from_optional    : std::integral_constant<          bool, is_constructible_convertible_from_optional<T, U>::value ||                    std::is_assignable<T&, optional<U>&>::value ||                    std::is_assignable<T&, optional<U>&&>::value ||                    std::is_assignable<T&, const optional<U>&>::value ||                    std::is_assignable<T&, const optional<U>&&>::value> {};// Helper function used by [optional.relops], [optional.comp_with_t],// for checking whether an expression is convertible to bool.bool convertible_to_bool(bool);// Base class for std::hash<absl::optional<T>>:// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to// compute the hash; Otherwise, it is disabled.// Reference N4659 23.14.15 [unord.hash].template <typename T, typename = size_t>struct optional_hash_base {  optional_hash_base() = delete;  optional_hash_base(const optional_hash_base&) = delete;  optional_hash_base(optional_hash_base&&) = delete;  optional_hash_base& operator=(const optional_hash_base&) = delete;  optional_hash_base& operator=(optional_hash_base&&) = delete;};template <typename T>struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(                                 std::declval<absl::remove_const_t<T> >()))> {  using argument_type = absl::optional<T>;  using result_type = size_t;  size_t operator()(const absl::optional<T>& opt) const {    absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();    if (opt) {      return std::hash<absl::remove_const_t<T> >()(*opt);    } else {      return static_cast<size_t>(0x297814aaad196e6dULL);    }  }};}  // namespace optional_internalABSL_NAMESPACE_END}  // namespace absl#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS#endif  // ABSL_TYPES_INTERNAL_OPTIONAL_H_
 |