Home | History | Annotate | Download | only in gtl
      1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 #ifndef TENSORFLOW_LIB_GTL_OPTIONAL_H_
     17 #define TENSORFLOW_LIB_GTL_OPTIONAL_H_
     18 
     19 #include <assert.h>
     20 #include <functional>
     21 #include <initializer_list>
     22 #include <type_traits>
     23 #include <utility>
     24 
     25 #include "tensorflow/core/platform/logging.h"
     26 
     27 namespace tensorflow {
     28 namespace gtl {
     29 
     30 // A value of type gtl::optional<T> holds either a value of T or an
     31 // "empty" value.  When it holds a value of T, it stores it as a direct
     32 // subobject, so sizeof(optional<T>) is approximately sizeof(T)+1. The interface
     33 // is based on the upcoming std::optional<T>, and gtl::optional<T> is
     34 // designed to be cheaply drop-in replaceable by std::optional<T>, once it is
     35 // rolled out.
     36 //
     37 // This implementation is based on the specification in the latest draft as of
     38 // 2017-01-05, section 20.6.
     39 //
     40 // Differences between gtl::optional<T> and std::optional<T> include:
     41 //    - constexpr not used for nonconst member functions.
     42 //      (dependency on some differences between C++11 and C++14.)
     43 //    - nullopt and in_place are not constexpr. We need the inline variable
     44 //      support in C++17 for external linkage.
     45 //    - CHECK instead of throwing std::bad_optional_access.
     46 //    - optional::swap() and swap() relies on std::is_(nothrow_)swappable
     47 //      which is introduced in C++17. So we assume is_swappable is always true
     48 //      and is_nothrow_swappable is same as std::is_trivial.
     49 //    - make_optional cannot be constexpr due to absence of guaranteed copy
     50 //      elision.
     51 //
     52 // Synopsis:
     53 //
     54 //     #include "tensorflow/core/lib/gtl/optional.h"
     55 //
     56 //     tensorflow::gtl::optional<string> f() {
     57 //       string result;
     58 //       if (...) {
     59 //          ...
     60 //          result = ...;
     61 //          return result;
     62 //       } else {
     63 //          ...
     64 //          return tensorflow::gtl::nullopt;
     65 //       }
     66 //     }
     67 //
     68 //     int main() {
     69 //         tensorflow::gtl::optional<string> optstr = f();
     70 //         if (optstr) {
     71 //            // non-empty
     72 //            print(optstr.value());
     73 //         } else {
     74 //            // empty
     75 //            error();
     76 //         }
     77 //     }
     78 template <typename T>
     79 class optional;
     80 
     81 // The tag constant `in_place` is used as the first parameter of an optional<T>
     82 // constructor to indicate that the remaining arguments should be forwarded
     83 // to the underlying T constructor.
     84 struct in_place_t {};
     85 extern const in_place_t in_place;
     86 
     87 // The tag constant `nullopt` is used to indicate an empty optional<T> in
     88 // certain functions, such as construction or assignment.
     89 struct nullopt_t {
     90   struct init_t {};
     91   static init_t init;
     92   // It must not be default-constructible to avoid ambiguity for opt = {}.
     93   // Note the non-const reference, it is to eliminate ambiguity for code like:
     94   // struct S { int value; };
     95   //
     96   // void Test() {
     97   //   optional<S> opt;
     98   //   opt = {{}};
     99   // }
    100   explicit constexpr nullopt_t(init_t& /*unused*/) {}  // NOLINT
    101 };
    102 extern const nullopt_t nullopt;
    103 
    104 namespace internal_optional {
    105 
    106 // define forward locally because std::forward is not constexpr until C++14
    107 template <typename T>
    108 constexpr T&& forward(typename std::remove_reference<T>::type&
    109                           t) noexcept {  // NOLINT(runtime/references)
    110   return static_cast<T&&>(t);
    111 }
    112 
    113 struct empty_struct {};
    114 // This class stores the data in optional<T>.
    115 // It is specialized based on whether T is trivially destructible.
    116 // This is the specialization for non trivially destructible type.
    117 template <typename T, bool = std::is_trivially_destructible<T>::value>
    118 class optional_data_dtor_base {
    119  protected:
    120   // Whether there is data or not.
    121   bool engaged_;
    122   // data storage
    123   union {
    124     empty_struct dummy_;
    125     T data_;
    126   };
    127 
    128   void destruct() noexcept {
    129     if (engaged_) {
    130       data_.~T();
    131       engaged_ = false;
    132     }
    133   }
    134 
    135   // dummy_ must be initialized for constexpr constructor
    136   constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{} {}
    137 
    138   template <typename... Args>
    139   constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
    140       : engaged_(true), data_(internal_optional::forward<Args>(args)...) {}
    141 
    142   ~optional_data_dtor_base() { destruct(); }
    143 };
    144 
    145 // Specialization for trivially destructible type.
    146 template <typename T>
    147 class optional_data_dtor_base<T, true> {
    148  protected:
    149   // Whether there is data or not.
    150   bool engaged_;
    151   // data storage
    152   union {
    153     empty_struct dummy_;
    154     T data_;
    155   };
    156   void destruct() noexcept { engaged_ = false; }
    157 
    158   // dummy_ must be initialized for constexpr constructor
    159   constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{} {}
    160 
    161   template <typename... Args>
    162   constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
    163       : engaged_(true), data_(internal_optional::forward<Args>(args)...) {}
    164 
    165   ~optional_data_dtor_base() = default;
    166 };
    167 
    168 template <typename T>
    169 class optional_data : public optional_data_dtor_base<T> {
    170  protected:
    171   using base = optional_data_dtor_base<T>;
    172   using base::base;
    173 
    174   T* pointer() { return &this->data_; }
    175 
    176   constexpr const T* pointer() const { return &this->data_; }
    177 
    178   template <typename... Args>
    179   void construct(Args&&... args) {
    180     new (pointer()) T(std::forward<Args>(args)...);
    181     this->engaged_ = true;
    182   }
    183 
    184   template <typename U>
    185   void assign(U&& u) {
    186     if (this->engaged_) {
    187       this->data_ = std::forward<U>(u);
    188     } else {
    189       construct(std::forward<U>(u));
    190     }
    191   }
    192 
    193   optional_data() = default;
    194 
    195   optional_data(const optional_data& rhs) {
    196     if (rhs.engaged_) {
    197       construct(rhs.data_);
    198     }
    199   }
    200 
    201   optional_data(optional_data&& rhs) noexcept(
    202       std::is_nothrow_move_constructible<T>::value) {
    203     if (rhs.engaged_) {
    204       construct(std::move(rhs.data_));
    205     }
    206   }
    207 
    208   optional_data& operator=(const optional_data& rhs) {
    209     if (rhs.engaged_) {
    210       assign(rhs.data_);
    211     } else {
    212       this->destruct();
    213     }
    214     return *this;
    215   }
    216 
    217   optional_data& operator=(optional_data&& rhs) noexcept(
    218       std::is_nothrow_move_assignable<T>::value&&
    219           std::is_nothrow_move_constructible<T>::value) {
    220     if (rhs.engaged_) {
    221       assign(std::move(rhs.data_));
    222     } else {
    223       this->destruct();
    224     }
    225     return *this;
    226   }
    227 };
    228 
    229 // ordered by level of restriction, from low to high.
    230 // copyable implies movable.
    231 enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
    232 
    233 // base class for enabling/disabling copy/move constructor.
    234 template <copy_traits>
    235 class optional_ctor_base;
    236 
    237 template <>
    238 class optional_ctor_base<copy_traits::copyable> {
    239  public:
    240   constexpr optional_ctor_base() = default;
    241   optional_ctor_base(const optional_ctor_base&) = default;
    242   optional_ctor_base(optional_ctor_base&&) = default;
    243   optional_ctor_base& operator=(const optional_ctor_base&) = default;
    244   optional_ctor_base& operator=(optional_ctor_base&&) = default;
    245 };
    246 
    247 template <>
    248 class optional_ctor_base<copy_traits::movable> {
    249  public:
    250   constexpr optional_ctor_base() = default;
    251   optional_ctor_base(const optional_ctor_base&) = delete;
    252   optional_ctor_base(optional_ctor_base&&) = default;
    253   optional_ctor_base& operator=(const optional_ctor_base&) = default;
    254   optional_ctor_base& operator=(optional_ctor_base&&) = default;
    255 };
    256 
    257 template <>
    258 class optional_ctor_base<copy_traits::non_movable> {
    259  public:
    260   constexpr optional_ctor_base() = default;
    261   optional_ctor_base(const optional_ctor_base&) = delete;
    262   optional_ctor_base(optional_ctor_base&&) = delete;
    263   optional_ctor_base& operator=(const optional_ctor_base&) = default;
    264   optional_ctor_base& operator=(optional_ctor_base&&) = default;
    265 };
    266 
    267 // base class for enabling/disabling copy/move assignment.
    268 template <copy_traits>
    269 class optional_assign_base;
    270 
    271 template <>
    272 class optional_assign_base<copy_traits::copyable> {
    273  public:
    274   constexpr optional_assign_base() = default;
    275   optional_assign_base(const optional_assign_base&) = default;
    276   optional_assign_base(optional_assign_base&&) = default;
    277   optional_assign_base& operator=(const optional_assign_base&) = default;
    278   optional_assign_base& operator=(optional_assign_base&&) = default;
    279 };
    280 
    281 template <>
    282 class optional_assign_base<copy_traits::movable> {
    283  public:
    284   constexpr optional_assign_base() = default;
    285   optional_assign_base(const optional_assign_base&) = default;
    286   optional_assign_base(optional_assign_base&&) = default;
    287   optional_assign_base& operator=(const optional_assign_base&) = delete;
    288   optional_assign_base& operator=(optional_assign_base&&) = default;
    289 };
    290 
    291 template <>
    292 class optional_assign_base<copy_traits::non_movable> {
    293  public:
    294   constexpr optional_assign_base() = default;
    295   optional_assign_base(const optional_assign_base&) = default;
    296   optional_assign_base(optional_assign_base&&) = default;
    297   optional_assign_base& operator=(const optional_assign_base&) = delete;
    298   optional_assign_base& operator=(optional_assign_base&&) = delete;
    299 };
    300 
    301 template <typename T>
    302 constexpr copy_traits get_ctor_copy_traits() {
    303   return std::is_copy_constructible<T>::value
    304              ? copy_traits::copyable
    305              : std::is_move_constructible<T>::value ? copy_traits::movable
    306                                                     : copy_traits::non_movable;
    307 }
    308 
    309 template <typename T>
    310 constexpr copy_traits get_assign_copy_traits() {
    311   return std::is_copy_assignable<T>::value &&
    312                  std::is_copy_constructible<T>::value
    313              ? copy_traits::copyable
    314              : std::is_move_assignable<T>::value &&
    315                        std::is_move_constructible<T>::value
    316                    ? copy_traits::movable
    317                    : copy_traits::non_movable;
    318 }
    319 
    320 // Whether T is constructible or convertible from optional<U>.
    321 template <typename T, typename U>
    322 struct is_constructible_convertible_from_optional
    323     : std::integral_constant<
    324           bool, std::is_constructible<T, optional<U>&>::value ||
    325                     std::is_constructible<T, optional<U>&&>::value ||
    326                     std::is_constructible<T, const optional<U>&>::value ||
    327                     std::is_constructible<T, const optional<U>&&>::value ||
    328                     std::is_convertible<optional<U>&, T>::value ||
    329                     std::is_convertible<optional<U>&&, T>::value ||
    330                     std::is_convertible<const optional<U>&, T>::value ||
    331                     std::is_convertible<const optional<U>&&, T>::value> {};
    332 
    333 // Whether T is constructible or convertible or assignable from optional<U>.
    334 template <typename T, typename U>
    335 struct is_constructible_convertible_assignable_from_optional
    336     : std::integral_constant<
    337           bool, is_constructible_convertible_from_optional<T, U>::value ||
    338                     std::is_assignable<T&, optional<U>&>::value ||
    339                     std::is_assignable<T&, optional<U>&&>::value ||
    340                     std::is_assignable<T&, const optional<U>&>::value ||
    341                     std::is_assignable<T&, const optional<U>&&>::value> {};
    342 
    343 }  // namespace internal_optional
    344 
    345 template <typename T>
    346 class optional : private internal_optional::optional_data<T>,
    347                  private internal_optional::optional_ctor_base<
    348                      internal_optional::get_ctor_copy_traits<T>()>,
    349                  private internal_optional::optional_assign_base<
    350                      internal_optional::get_assign_copy_traits<T>()> {
    351   using data_base = internal_optional::optional_data<T>;
    352 
    353  public:
    354   typedef T value_type;
    355 
    356   // [optional.ctor], constructors
    357 
    358   // A default constructed optional holds the empty value, NOT a default
    359   // constructed T.
    360   constexpr optional() noexcept {}
    361 
    362   // An optional initialized with `nullopt` holds the empty value.
    363   constexpr optional(nullopt_t) noexcept {}  // NOLINT(runtime/explicit)
    364 
    365   // Copy constructor, standard semantics.
    366   optional(const optional& src) = default;
    367 
    368   // Move constructor, standard semantics.
    369   optional(optional&& src) = default;
    370 
    371   // optional<T>(in_place, arg1, arg2, arg3) constructs a non-empty optional
    372   // with an in-place constructed value of T(arg1,arg2,arg3).
    373   // TODO(b/34201852): Add std::is_constructible<T, Args&&...> SFINAE.
    374   template <typename... Args>
    375   constexpr explicit optional(in_place_t, Args&&... args)
    376       : data_base(in_place_t(), internal_optional::forward<Args>(args)...) {}
    377 
    378   // optional<T>(in_place, {arg1, arg2, arg3}) constructs a non-empty optional
    379   // with an in-place list-initialized value of T({arg1, arg2, arg3}).
    380   template <typename U, typename... Args,
    381             typename = typename std::enable_if<std::is_constructible<
    382                 T, std::initializer_list<U>&, Args&&...>::value>::type>
    383   constexpr explicit optional(in_place_t, std::initializer_list<U> il,
    384                               Args&&... args)
    385       : data_base(in_place_t(), il, internal_optional::forward<Args>(args)...) {
    386   }
    387 
    388   template <
    389       typename U = T,
    390       typename std::enable_if<
    391           std::is_constructible<T, U&&>::value &&
    392               !std::is_same<in_place_t, typename std::decay<U>::type>::value &&
    393               !std::is_same<optional<T>, typename std::decay<U>::type>::value &&
    394               std::is_convertible<U&&, T>::value,
    395           bool>::type = false>
    396   constexpr optional(U&& v)  // NOLINT
    397       : data_base(in_place_t(), internal_optional::forward<U>(v)) {}
    398 
    399   template <
    400       typename U = T,
    401       typename std::enable_if<
    402           std::is_constructible<T, U&&>::value &&
    403               !std::is_same<in_place_t, typename std::decay<U>::type>::value &&
    404               !std::is_same<optional<T>, typename std::decay<U>::type>::value &&
    405               !std::is_convertible<U&&, T>::value,
    406           bool>::type = false>
    407   explicit constexpr optional(U&& v)
    408       : data_base(in_place_t(), internal_optional::forward<U>(v)) {}
    409 
    410   // Converting copy constructor (implicit)
    411   template <
    412       typename U,
    413       typename std::enable_if<
    414           std::is_constructible<T, const U&>::value &&
    415               !internal_optional::is_constructible_convertible_from_optional<
    416                   T, U>::value &&
    417               std::is_convertible<const U&, T>::value,
    418           bool>::type = false>
    419   optional(const optional<U>& rhs) {  // NOLINT
    420     if (rhs) {
    421       this->construct(*rhs);
    422     }
    423   }
    424 
    425   // Converting copy constructor (explicit)
    426   template <
    427       typename U,
    428       typename std::enable_if<
    429           std::is_constructible<T, const U&>::value &&
    430               !internal_optional::is_constructible_convertible_from_optional<
    431                   T, U>::value &&
    432               !std::is_convertible<const U&, T>::value,
    433           bool>::type = false>
    434   explicit optional(const optional<U>& rhs) {
    435     if (rhs) {
    436       this->construct(*rhs);
    437     }
    438   }
    439 
    440   // Converting move constructor (implicit)
    441   template <
    442       typename U,
    443       typename std::enable_if<
    444           std::is_constructible<T, U&&>::value &&
    445               !internal_optional::is_constructible_convertible_from_optional<
    446                   T, U>::value &&
    447               std::is_convertible<U&&, T>::value,
    448           bool>::type = false>
    449   optional(optional<U>&& rhs) {  // NOLINT
    450     if (rhs) {
    451       this->construct(std::move(*rhs));
    452     }
    453   }
    454 
    455   // Converting move constructor (explicit)
    456   template <
    457       typename U,
    458       typename std::enable_if<
    459           std::is_constructible<T, U&&>::value &&
    460               !internal_optional::is_constructible_convertible_from_optional<
    461                   T, U>::value &&
    462               !std::is_convertible<U&&, T>::value,
    463           bool>::type = false>
    464   explicit optional(optional<U>&& rhs) {
    465     if (rhs) {
    466       this->construct(std::move(*rhs));
    467     }
    468   }
    469 
    470   // [optional.dtor], destructor, trivial if T is trivially destructible.
    471   ~optional() = default;
    472 
    473   // [optional.assign], assignment
    474 
    475   // Assignment from nullopt: opt = nullopt
    476   optional& operator=(nullopt_t) noexcept {
    477     this->destruct();
    478     return *this;
    479   }
    480 
    481   // Copy assignment, standard semantics.
    482   optional& operator=(const optional& src) = default;
    483 
    484   // Move assignment, standard semantics.
    485   optional& operator=(optional&& src) = default;
    486 
    487   // Value assignment
    488   template <
    489       typename U = T,
    490       typename = typename std::enable_if<
    491           !std::is_same<optional<T>, typename std::decay<U>::type>::value &&
    492           (!std::is_scalar<T>::value ||
    493            !std::is_same<T, typename std::decay<U>::type>::value) &&
    494           std::is_constructible<T, U>::value &&
    495           std::is_assignable<T&, U>::value>::type>
    496   optional& operator=(U&& v) {
    497     this->assign(std::forward<U>(v));
    498     return *this;
    499   }
    500 
    501   template <typename U,
    502             typename = typename std::enable_if<
    503                 std::is_constructible<T, const U&>::value &&
    504                 std::is_assignable<T&, const U&>::value &&
    505                 !internal_optional::
    506                     is_constructible_convertible_assignable_from_optional<
    507                         T, U>::value>::type>
    508   optional& operator=(const optional<U>& rhs) {
    509     if (rhs) {
    510       this->assign(*rhs);
    511     } else {
    512       this->destruct();
    513     }
    514     return *this;
    515   }
    516 
    517   template <typename U,
    518             typename = typename std::enable_if<
    519                 std::is_constructible<T, U>::value &&
    520                 std::is_assignable<T&, U>::value &&
    521                 !internal_optional::
    522                     is_constructible_convertible_assignable_from_optional<
    523                         T, U>::value>::type>
    524   optional& operator=(optional<U>&& rhs) {
    525     if (rhs) {
    526       this->assign(std::move(*rhs));
    527     } else {
    528       this->destruct();
    529     }
    530     return *this;
    531   }
    532 
    533   // [optional.mod], modifiers
    534   // Destroys the inner T value if one is present.
    535   void reset() noexcept { this->destruct(); }
    536 
    537   // Emplace reconstruction.  (Re)constructs the underlying T in-place with the
    538   // given arguments forwarded:
    539   //
    540   // optional<Foo> opt;
    541   // opt.emplace(arg1,arg2,arg3);  (Constructs Foo(arg1,arg2,arg3))
    542   //
    543   // If the optional is non-empty, and the `args` refer to subobjects of the
    544   // current object, then behavior is undefined.  This is because the current
    545   // object will be destructed before the new object is constructed with `args`.
    546   //
    547   template <typename... Args,
    548             typename = typename std::enable_if<
    549                 std::is_constructible<T, Args&&...>::value>::type>
    550   void emplace(Args&&... args) {
    551     this->destruct();
    552     this->construct(std::forward<Args>(args)...);
    553   }
    554 
    555   // Emplace reconstruction with initializer-list.  See immediately above.
    556   template <class U, class... Args,
    557             typename = typename std::enable_if<std::is_constructible<
    558                 T, std::initializer_list<U>&, Args&&...>::value>::type>
    559   void emplace(std::initializer_list<U> il, Args&&... args) {
    560     this->destruct();
    561     this->construct(il, std::forward<Args>(args)...);
    562   }
    563 
    564   // [optional.swap], swap
    565   // Swap, standard semantics.
    566   void swap(optional& rhs) noexcept(
    567       std::is_nothrow_move_constructible<T>::value&&
    568           std::is_trivial<T>::value) {
    569     if (*this) {
    570       if (rhs) {
    571         using std::swap;
    572         swap(**this, *rhs);
    573       } else {
    574         rhs.construct(std::move(**this));
    575         this->destruct();
    576       }
    577     } else {
    578       if (rhs) {
    579         this->construct(std::move(*rhs));
    580         rhs.destruct();
    581       } else {
    582         // no effect (swap(disengaged, disengaged))
    583       }
    584     }
    585   }
    586 
    587   // [optional.observe], observers
    588   // You may use `*opt`, and `opt->m`, to access the underlying T value and T's
    589   // member `m`, respectively.  If the optional is empty, behavior is
    590   // undefined.
    591   constexpr const T* operator->() const { return this->pointer(); }
    592   T* operator->() {
    593     assert(this->engaged_);
    594     return this->pointer();
    595   }
    596   constexpr const T& operator*() const& { return reference(); }
    597   T& operator*() & {
    598     assert(this->engaged_);
    599     return reference();
    600   }
    601   constexpr const T&& operator*() const&& { return std::move(reference()); }
    602   T&& operator*() && {
    603     assert(this->engaged_);
    604     return std::move(reference());
    605   }
    606 
    607   // In a bool context an optional<T> will return false if and only if it is
    608   // empty.
    609   //
    610   //   if (opt) {
    611   //     // do something with opt.value();
    612   //   } else {
    613   //     // opt is empty
    614   //   }
    615   //
    616   constexpr explicit operator bool() const noexcept { return this->engaged_; }
    617 
    618   // Returns false if and only if *this is empty.
    619   constexpr bool has_value() const noexcept { return this->engaged_; }
    620 
    621   // Use `opt.value()` to get a reference to underlying value.  The constness
    622   // and lvalue/rvalue-ness of `opt` is preserved to the view of the T
    623   // subobject.
    624   const T& value() const& {
    625     CHECK(*this) << "Bad optional access";
    626     return reference();
    627   }
    628   T& value() & {
    629     CHECK(*this) << "Bad optional access";
    630     return reference();
    631   }
    632   T&& value() && {  // NOLINT(build/c++11)
    633     CHECK(*this) << "Bad optional access";
    634     return std::move(reference());
    635   }
    636   const T&& value() const&& {  // NOLINT(build/c++11)
    637     CHECK(*this) << "Bad optional access";
    638     return std::move(reference());
    639   }
    640 
    641   // Use `opt.value_or(val)` to get either the value of T or the given default
    642   // `val` in the empty case.
    643   template <class U>
    644   constexpr T value_or(U&& v) const& {
    645     return static_cast<bool>(*this) ? **this
    646                                     : static_cast<T>(std::forward<U>(v));
    647   }
    648   template <class U>
    649   T value_or(U&& v) && {  // NOLINT(build/c++11)
    650     return static_cast<bool>(*this) ? std::move(**this)
    651                                     : static_cast<T>(std::forward<U>(v));
    652   }
    653 
    654  private:
    655   // Private accessors for internal storage viewed as reference to T.
    656   constexpr const T& reference() const { return *this->pointer(); }
    657   T& reference() { return *(this->pointer()); }
    658 
    659   // T constraint checks.  You can't have an optional of nullopt_t, in_place_t
    660   // or a reference.
    661   static_assert(
    662       !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value,
    663       "optional<nullopt_t> is not allowed.");
    664   static_assert(
    665       !std::is_same<in_place_t, typename std::remove_cv<T>::type>::value,
    666       "optional<in_place_t> is not allowed.");
    667   static_assert(!std::is_reference<T>::value,
    668                 "optional<reference> is not allowed.");
    669 };
    670 
    671 // [optional.specalg]
    672 // Swap, standard semantics.
    673 // This function shall not participate in overload resolution unless
    674 // is_move_constructible_v<T> is true and is_swappable_v<T> is true.
    675 // NOTE: we assume is_swappable is always true. There will be a compiling error
    676 // if T is actually not Swappable.
    677 template <typename T,
    678           typename std::enable_if<std::is_move_constructible<T>::value,
    679                                   bool>::type = false>
    680 void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
    681   a.swap(b);
    682 }
    683 
    684 // NOTE: make_optional cannot be constexpr in C++11 because the copy/move
    685 // constructor is not constexpr and we don't have guaranteed copy elision
    686 // util C++17. But they are still declared constexpr for consistency with
    687 // the standard.
    688 
    689 // make_optional(v) creates a non-empty optional<T> where the type T is deduced
    690 // from v.  Can also be explicitly instantiated as make_optional<T>(v).
    691 template <typename T>
    692 constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
    693   return optional<typename std::decay<T>::type>(std::forward<T>(v));
    694 }
    695 
    696 template <typename T, typename... Args>
    697 constexpr optional<T> make_optional(Args&&... args) {
    698   return optional<T>(in_place_t(), internal_optional::forward<Args>(args)...);
    699 }
    700 
    701 template <typename T, typename U, typename... Args>
    702 constexpr optional<T> make_optional(std::initializer_list<U> il,
    703                                     Args&&... args) {
    704   return optional<T>(in_place_t(), il,
    705                      internal_optional::forward<Args>(args)...);
    706 }
    707 
    708 // Relational operators. Empty optionals are considered equal to each
    709 // other and less than non-empty optionals. Supports relations between
    710 // optional<T> and optional<T>, between optional<T> and T, and between
    711 // optional<T> and nullopt.
    712 // Note: We're careful to support T having non-bool relationals.
    713 
    714 // Relational operators [optional.relops]
    715 // The C++17 (N4606) "Returns:" statements are translated into code
    716 // in an obvious way here, and the original text retained as function docs.
    717 // Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true;
    718 // otherwise *x == *y.
    719 template <class T>
    720 constexpr bool operator==(const optional<T>& x, const optional<T>& y) {
    721   return static_cast<bool>(x) != static_cast<bool>(y)
    722              ? false
    723              : static_cast<bool>(x) == false ? true : *x == *y;
    724 }
    725 // Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false;
    726 // otherwise *x != *y.
    727 template <class T>
    728 constexpr bool operator!=(const optional<T>& x, const optional<T>& y) {
    729   return static_cast<bool>(x) != static_cast<bool>(y)
    730              ? true
    731              : static_cast<bool>(x) == false ? false : *x != *y;
    732 }
    733 // Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y.
    734 template <class T>
    735 constexpr bool operator<(const optional<T>& x, const optional<T>& y) {
    736   return !y ? false : !x ? true : *x < *y;
    737 }
    738 // Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y.
    739 template <class T>
    740 constexpr bool operator>(const optional<T>& x, const optional<T>& y) {
    741   return !x ? false : !y ? true : *x > *y;
    742 }
    743 // Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y.
    744 template <class T>
    745 constexpr bool operator<=(const optional<T>& x, const optional<T>& y) {
    746   return !x ? true : !y ? false : *x <= *y;
    747 }
    748 // Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y.
    749 template <class T>
    750 constexpr bool operator>=(const optional<T>& x, const optional<T>& y) {
    751   return !y ? true : !x ? false : *x >= *y;
    752 }
    753 
    754 // Comparison with nullopt [optional.nullops]
    755 // The C++17 (N4606) "Returns:" statements are used directly here.
    756 template <class T>
    757 constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
    758   return !x;
    759 }
    760 template <class T>
    761 constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
    762   return !x;
    763 }
    764 template <class T>
    765 constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
    766   return static_cast<bool>(x);
    767 }
    768 template <class T>
    769 constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
    770   return static_cast<bool>(x);
    771 }
    772 template <class T>
    773 constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept {
    774   return false;
    775 }
    776 template <class T>
    777 constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
    778   return static_cast<bool>(x);
    779 }
    780 template <class T>
    781 constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
    782   return !x;
    783 }
    784 template <class T>
    785 constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept {
    786   return true;
    787 }
    788 template <class T>
    789 constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
    790   return static_cast<bool>(x);
    791 }
    792 template <class T>
    793 constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept {
    794   return false;
    795 }
    796 template <class T>
    797 constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept {
    798   return true;
    799 }
    800 template <class T>
    801 constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
    802   return !x;
    803 }
    804 
    805 // Comparison with T [optional.comp_with_t]
    806 // The C++17 (N4606) "Equivalent to:" statements are used directly here.
    807 template <class T>
    808 constexpr bool operator==(const optional<T>& x, const T& v) {
    809   return static_cast<bool>(x) ? *x == v : false;
    810 }
    811 template <class T>
    812 constexpr bool operator==(const T& v, const optional<T>& x) {
    813   return static_cast<bool>(x) ? v == *x : false;
    814 }
    815 template <class T>
    816 constexpr bool operator!=(const optional<T>& x, const T& v) {
    817   return static_cast<bool>(x) ? *x != v : true;
    818 }
    819 template <class T>
    820 constexpr bool operator!=(const T& v, const optional<T>& x) {
    821   return static_cast<bool>(x) ? v != *x : true;
    822 }
    823 template <class T>
    824 constexpr bool operator<(const optional<T>& x, const T& v) {
    825   return static_cast<bool>(x) ? *x < v : true;
    826 }
    827 template <class T>
    828 constexpr bool operator<(const T& v, const optional<T>& x) {
    829   return static_cast<bool>(x) ? v < *x : false;
    830 }
    831 template <class T>
    832 constexpr bool operator<=(const optional<T>& x, const T& v) {
    833   return static_cast<bool>(x) ? *x <= v : true;
    834 }
    835 template <class T>
    836 constexpr bool operator<=(const T& v, const optional<T>& x) {
    837   return static_cast<bool>(x) ? v <= *x : false;
    838 }
    839 template <class T>
    840 constexpr bool operator>(const optional<T>& x, const T& v) {
    841   return static_cast<bool>(x) ? *x > v : false;
    842 }
    843 template <class T>
    844 constexpr bool operator>(const T& v, const optional<T>& x) {
    845   return static_cast<bool>(x) ? v > *x : true;
    846 }
    847 template <class T>
    848 constexpr bool operator>=(const optional<T>& x, const T& v) {
    849   return static_cast<bool>(x) ? *x >= v : false;
    850 }
    851 template <class T>
    852 constexpr bool operator>=(const T& v, const optional<T>& x) {
    853   return static_cast<bool>(x) ? v >= *x : true;
    854 }
    855 
    856 }  // namespace gtl
    857 }  // namespace tensorflow
    858 
    859 namespace std {
    860 
    861 // Normally std::hash specializations are not recommended in tensorflow code,
    862 // but we allow this as it is following a standard library component.
    863 template <class T>
    864 struct hash<::tensorflow::gtl::optional<T>> {
    865   size_t operator()(const ::tensorflow::gtl::optional<T>& opt) const {
    866     if (opt) {
    867       return hash<T>()(*opt);
    868     } else {
    869       return static_cast<size_t>(0x297814aaad196e6dULL);
    870     }
    871   }
    872 };
    873 
    874 }  // namespace std
    875 
    876 #endif  // TENSORFLOW_LIB_GTL_OPTIONAL_H_
    877