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 #include "tensorflow/core/lib/gtl/optional.h"
     17 
     18 #include <string>
     19 #include <utility>
     20 
     21 #include "tensorflow/core/platform/test.h"
     22 #include "tensorflow/core/platform/types.h"
     23 
     24 namespace tensorflow {
     25 namespace {
     26 
     27 using tensorflow::gtl::in_place;
     28 using tensorflow::gtl::in_place_t;
     29 using tensorflow::gtl::make_optional;
     30 using tensorflow::gtl::nullopt;
     31 using tensorflow::gtl::nullopt_t;
     32 using tensorflow::gtl::optional;
     33 
     34 template <typename T>
     35 string TypeQuals(T&) {
     36   return "&";
     37 }
     38 template <typename T>
     39 string TypeQuals(T&&) {
     40   return "&&";
     41 }
     42 template <typename T>
     43 string TypeQuals(const T&) {
     44   return "c&";
     45 }
     46 template <typename T>
     47 string TypeQuals(const T&&) {
     48   return "c&&";
     49 }
     50 
     51 struct StructorListener {
     52   int construct0 = 0;
     53   int construct1 = 0;
     54   int construct2 = 0;
     55   int listinit = 0;
     56   int copy = 0;
     57   int move = 0;
     58   int copy_assign = 0;
     59   int move_assign = 0;
     60   int destruct = 0;
     61 };
     62 
     63 struct Listenable {
     64   static StructorListener* listener;
     65 
     66   Listenable() { ++listener->construct0; }
     67   Listenable(int /*unused*/) { ++listener->construct1; }  // NOLINT
     68   Listenable(int /*unused*/, int /*unused*/) { ++listener->construct2; }
     69   Listenable(std::initializer_list<int> /*unused*/) { ++listener->listinit; }
     70   Listenable(const Listenable& /*unused*/) { ++listener->copy; }
     71   Listenable(Listenable&& /*unused*/) { ++listener->move; }  // NOLINT
     72   Listenable& operator=(const Listenable& /*unused*/) {
     73     ++listener->copy_assign;
     74     return *this;
     75   }
     76   Listenable& operator=(Listenable&& /*unused*/) {  // NOLINT
     77     ++listener->move_assign;
     78     return *this;
     79   }
     80   ~Listenable() { ++listener->destruct; }
     81 };
     82 
     83 StructorListener* Listenable::listener = nullptr;
     84 
     85 // clang on macos -- even the latest major version at time of writing (8.x) --
     86 // does not like much of our constexpr business.  clang < 3.0 also has trouble.
     87 #if defined(__clang__) && defined(__APPLE__)
     88 #define SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG
     89 #endif
     90 
     91 struct ConstexprType {
     92   constexpr ConstexprType() : x(0) {}
     93   constexpr explicit ConstexprType(int i) : x(i) {}
     94 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG
     95   constexpr ConstexprType(std::initializer_list<int> il) : x(il.size()) {}
     96 #endif
     97   constexpr ConstexprType(const char* s) : x(-1) {}  // NOLINT
     98   int x;
     99 };
    100 
    101 struct Copyable {
    102   Copyable() {}
    103   Copyable(const Copyable&) {}
    104   Copyable& operator=(const Copyable&) { return *this; }
    105 };
    106 
    107 struct MoveableThrow {
    108   MoveableThrow() {}
    109   MoveableThrow(MoveableThrow&&) {}
    110   MoveableThrow& operator=(MoveableThrow&&) { return *this; }
    111 };
    112 
    113 struct MoveableNoThrow {
    114   MoveableNoThrow() {}
    115   MoveableNoThrow(MoveableNoThrow&&) noexcept {}
    116   MoveableNoThrow& operator=(MoveableNoThrow&&) noexcept { return *this; }
    117 };
    118 
    119 struct NonMovable {
    120   NonMovable() {}
    121   NonMovable(const NonMovable&) = delete;
    122   NonMovable& operator=(const NonMovable&) = delete;
    123   NonMovable(NonMovable&&) = delete;
    124   NonMovable& operator=(NonMovable&&) = delete;
    125 };
    126 
    127 TEST(optionalTest, DefaultConstructor) {
    128   optional<int> empty;
    129   EXPECT_FALSE(!!empty);
    130   constexpr optional<int> cempty;
    131   static_assert(!cempty.has_value(), "");
    132   EXPECT_TRUE(std::is_nothrow_default_constructible<optional<int>>::value);
    133 }
    134 
    135 TEST(optionalTest, NullOptConstructor) {
    136   optional<int> empty(nullopt);
    137   EXPECT_FALSE(!!empty);
    138   // Creating a temporary nullopt_t object instead of using nullopt because
    139   // nullopt cannot be constexpr and have external linkage at the same time.
    140   constexpr optional<int> cempty{nullopt_t(nullopt_t::init)};
    141   static_assert(!cempty.has_value(), "");
    142   EXPECT_TRUE((std::is_nothrow_constructible<optional<int>, nullopt_t>::value));
    143 }
    144 
    145 TEST(optionalTest, CopyConstructor) {
    146   optional<int> empty, opt42 = 42;
    147   optional<int> empty_copy(empty);
    148   EXPECT_FALSE(!!empty_copy);
    149   optional<int> opt42_copy(opt42);
    150   EXPECT_TRUE(!!opt42_copy);
    151   EXPECT_EQ(42, opt42_copy);
    152   // test copyablility
    153   EXPECT_TRUE(std::is_copy_constructible<optional<int>>::value);
    154   EXPECT_TRUE(std::is_copy_constructible<optional<Copyable>>::value);
    155   EXPECT_FALSE(std::is_copy_constructible<optional<MoveableThrow>>::value);
    156   EXPECT_FALSE(std::is_copy_constructible<optional<MoveableNoThrow>>::value);
    157   EXPECT_FALSE(std::is_copy_constructible<optional<NonMovable>>::value);
    158 }
    159 
    160 TEST(optionalTest, MoveConstructor) {
    161   optional<int> empty, opt42 = 42;
    162   optional<int> empty_move(std::move(empty));
    163   EXPECT_FALSE(!!empty_move);
    164   optional<int> opt42_move(std::move(opt42));
    165   EXPECT_TRUE(!!opt42_move);
    166   EXPECT_EQ(42, opt42_move);
    167   // test movability
    168   EXPECT_TRUE(std::is_move_constructible<optional<int>>::value);
    169   EXPECT_TRUE(std::is_move_constructible<optional<Copyable>>::value);
    170   EXPECT_TRUE(std::is_move_constructible<optional<MoveableThrow>>::value);
    171   EXPECT_TRUE(std::is_move_constructible<optional<MoveableNoThrow>>::value);
    172   EXPECT_FALSE(std::is_move_constructible<optional<NonMovable>>::value);
    173   // test noexcept
    174   EXPECT_TRUE(std::is_nothrow_move_constructible<optional<int>>::value);
    175   EXPECT_FALSE(
    176       std::is_nothrow_move_constructible<optional<MoveableThrow>>::value);
    177   EXPECT_TRUE(
    178       std::is_nothrow_move_constructible<optional<MoveableNoThrow>>::value);
    179 }
    180 
    181 TEST(optionalTest, Destructor) {
    182   struct Trivial {};
    183 
    184   struct NonTrivial {
    185     ~NonTrivial() {}
    186   };
    187 
    188   EXPECT_TRUE(std::is_trivially_destructible<optional<int>>::value);
    189   EXPECT_TRUE(std::is_trivially_destructible<optional<Trivial>>::value);
    190   EXPECT_FALSE(std::is_trivially_destructible<optional<NonTrivial>>::value);
    191 }
    192 
    193 TEST(optionalTest, InPlaceConstructor) {
    194   constexpr optional<ConstexprType> opt0{in_place_t()};
    195   static_assert(opt0, "");
    196   static_assert(opt0->x == 0, "");
    197   constexpr optional<ConstexprType> opt1{in_place_t(), 1};
    198   static_assert(opt1, "");
    199   static_assert(opt1->x == 1, "");
    200 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG
    201   constexpr optional<ConstexprType> opt2{in_place_t(), {1, 2}};
    202   static_assert(opt2, "");
    203   static_assert(opt2->x == 2, "");
    204 #endif
    205 
    206   // TODO(b/34201852): uncomment these when std::is_constructible<T, Args&&...>
    207   // SFINAE is added to optional::optional(in_place_t, Args&&...).
    208   // struct I {
    209   //   I(in_place_t);
    210   // };
    211 
    212   // EXPECT_FALSE((std::is_constructible<optional<I>, in_place_t>::value));
    213   // EXPECT_FALSE((std::is_constructible<optional<I>, const
    214   // in_place_t&>::value));
    215 }
    216 
    217 // template<U=T> optional(U&&);
    218 TEST(optionalTest, ValueConstructor) {
    219   constexpr optional<int> opt0(0);
    220   static_assert(opt0, "");
    221   static_assert(*opt0 == 0, "");
    222   EXPECT_TRUE((std::is_convertible<int, optional<int>>::value));
    223   // Copy initialization ( = "abc") won't work due to optional(optional&&)
    224   // is not constexpr. Use list initialization instead. This invokes
    225   // optional<ConstexprType>::optional<U>(U&&), with U = const char (&) [4],
    226   // which direct-initializes the ConstexprType value held by the optional
    227   // via ConstexprType::ConstexprType(const char*).
    228   constexpr optional<ConstexprType> opt1 = {"abc"};
    229   static_assert(opt1, "");
    230   static_assert(-1 == opt1->x, "");
    231   EXPECT_TRUE(
    232       (std::is_convertible<const char*, optional<ConstexprType>>::value));
    233   // direct initialization
    234   constexpr optional<ConstexprType> opt2{2};
    235   static_assert(opt2, "");
    236   static_assert(2 == opt2->x, "");
    237   EXPECT_FALSE((std::is_convertible<int, optional<ConstexprType>>::value));
    238 
    239   // this invokes optional<int>::optional(int&&)
    240   // NOTE: this has different behavior than assignment, e.g.
    241   // "opt3 = {};" clears the optional rather than setting the value to 0
    242   constexpr optional<int> opt3({});
    243   static_assert(opt3, "");
    244   static_assert(*opt3 == 0, "");
    245 
    246   // this invokes the move constructor with a default constructed optional
    247   // because non-template function is a better match than template function.
    248   optional<ConstexprType> opt4({});
    249   EXPECT_FALSE(!!opt4);
    250 }
    251 
    252 struct Implicit {};
    253 
    254 struct Explicit {};
    255 
    256 struct Convert {
    257   Convert(const Implicit&)  // NOLINT(runtime/explicit)
    258       : implicit(true), move(false) {}
    259   Convert(Implicit&&)  // NOLINT(runtime/explicit)
    260       : implicit(true), move(true) {}
    261   explicit Convert(const Explicit&) : implicit(false), move(false) {}
    262   explicit Convert(Explicit&&) : implicit(false), move(true) {}
    263 
    264   bool implicit;
    265   bool move;
    266 };
    267 
    268 struct ConvertFromOptional {
    269   ConvertFromOptional(const Implicit&)  // NOLINT(runtime/explicit)
    270       : implicit(true), move(false), from_optional(false) {}
    271   ConvertFromOptional(Implicit&&)  // NOLINT(runtime/explicit)
    272       : implicit(true), move(true), from_optional(false) {}
    273   ConvertFromOptional(const optional<Implicit>&)  // NOLINT(runtime/explicit)
    274       : implicit(true), move(false), from_optional(true) {}
    275   ConvertFromOptional(optional<Implicit>&&)  // NOLINT(runtime/explicit)
    276       : implicit(true), move(true), from_optional(true) {}
    277   explicit ConvertFromOptional(const Explicit&)
    278       : implicit(false), move(false), from_optional(false) {}
    279   explicit ConvertFromOptional(Explicit&&)
    280       : implicit(false), move(true), from_optional(false) {}
    281   explicit ConvertFromOptional(const optional<Explicit>&)
    282       : implicit(false), move(false), from_optional(true) {}
    283   explicit ConvertFromOptional(optional<Explicit>&&)
    284       : implicit(false), move(true), from_optional(true) {}
    285 
    286   bool implicit;
    287   bool move;
    288   bool from_optional;
    289 };
    290 
    291 TEST(optionalTest, ConvertingConstructor) {
    292   optional<Implicit> i_empty;
    293   optional<Implicit> i(in_place);
    294   optional<Explicit> e_empty;
    295   optional<Explicit> e(in_place);
    296   {
    297     // implicitly constructing optional<Convert> from optional<Implicit>
    298     optional<Convert> empty = i_empty;
    299     EXPECT_FALSE(!!empty);
    300     optional<Convert> opt_copy = i;
    301     EXPECT_TRUE(!!opt_copy);
    302     EXPECT_TRUE(opt_copy->implicit);
    303     EXPECT_FALSE(opt_copy->move);
    304     optional<Convert> opt_move = optional<Implicit>(in_place);
    305     EXPECT_TRUE(!!opt_move);
    306     EXPECT_TRUE(opt_move->implicit);
    307     EXPECT_TRUE(opt_move->move);
    308   }
    309   {
    310     // explicitly constructing optional<Convert> from optional<Explicit>
    311     optional<Convert> empty(e_empty);
    312     EXPECT_FALSE(!!empty);
    313     optional<Convert> opt_copy(e);
    314     EXPECT_TRUE(!!opt_copy);
    315     EXPECT_FALSE(opt_copy->implicit);
    316     EXPECT_FALSE(opt_copy->move);
    317     EXPECT_FALSE((std::is_convertible<const optional<Explicit>&,
    318                                       optional<Convert>>::value));
    319     optional<Convert> opt_move{optional<Explicit>(in_place)};
    320     EXPECT_TRUE(!!opt_move);
    321     EXPECT_FALSE(opt_move->implicit);
    322     EXPECT_TRUE(opt_move->move);
    323     EXPECT_FALSE(
    324         (std::is_convertible<optional<Explicit>&&, optional<Convert>>::value));
    325   }
    326   {
    327     // implicitly constructing optional<ConvertFromOptional> from
    328     // optional<Implicit> via ConvertFromOptional(optional<Implicit>&&)
    329     // check that ConvertFromOptional(Implicit&&) is NOT called
    330     static_assert(
    331         gtl::internal_optional::is_constructible_convertible_from_optional<
    332             ConvertFromOptional, Implicit>::value,
    333         "");
    334     optional<ConvertFromOptional> opt0 = i_empty;
    335     EXPECT_TRUE(!!opt0);
    336     EXPECT_TRUE(opt0->implicit);
    337     EXPECT_FALSE(opt0->move);
    338     EXPECT_TRUE(opt0->from_optional);
    339     optional<ConvertFromOptional> opt1 = optional<Implicit>();
    340     EXPECT_TRUE(!!opt1);
    341     EXPECT_TRUE(opt1->implicit);
    342     EXPECT_TRUE(opt1->move);
    343     EXPECT_TRUE(opt1->from_optional);
    344   }
    345   {
    346     // implicitly constructing optional<ConvertFromOptional> from
    347     // optional<Explicit> via ConvertFromOptional(optional<Explicit>&&)
    348     // check that ConvertFromOptional(Explicit&&) is NOT called
    349     optional<ConvertFromOptional> opt0(e_empty);
    350     EXPECT_TRUE(!!opt0);
    351     EXPECT_FALSE(opt0->implicit);
    352     EXPECT_FALSE(opt0->move);
    353     EXPECT_TRUE(opt0->from_optional);
    354     EXPECT_FALSE((std::is_convertible<const optional<Explicit>&,
    355                                       optional<ConvertFromOptional>>::value));
    356     optional<ConvertFromOptional> opt1{optional<Explicit>()};
    357     EXPECT_TRUE(!!opt1);
    358     EXPECT_FALSE(opt1->implicit);
    359     EXPECT_TRUE(opt1->move);
    360     EXPECT_TRUE(opt1->from_optional);
    361     EXPECT_FALSE((std::is_convertible<optional<Explicit>&&,
    362                                       optional<ConvertFromOptional>>::value));
    363   }
    364 }
    365 
    366 TEST(optionalTest, StructorBasic) {
    367   StructorListener listener;
    368   Listenable::listener = &listener;
    369   {
    370     optional<Listenable> empty;
    371     EXPECT_FALSE(!!empty);
    372     optional<Listenable> opt0(in_place);
    373     EXPECT_TRUE(!!opt0);
    374     optional<Listenable> opt1(in_place, 1);
    375     EXPECT_TRUE(!!opt1);
    376     optional<Listenable> opt2(in_place, 1, 2);
    377     EXPECT_TRUE(!!opt2);
    378   }
    379   EXPECT_EQ(1, listener.construct0);
    380   EXPECT_EQ(1, listener.construct1);
    381   EXPECT_EQ(1, listener.construct2);
    382   EXPECT_EQ(3, listener.destruct);
    383 }
    384 
    385 TEST(optionalTest, CopyMoveStructor) {
    386   StructorListener listener;
    387   Listenable::listener = &listener;
    388   optional<Listenable> original(in_place);
    389   EXPECT_EQ(1, listener.construct0);
    390   EXPECT_EQ(0, listener.copy);
    391   EXPECT_EQ(0, listener.move);
    392   optional<Listenable> copy(original);
    393   EXPECT_EQ(1, listener.construct0);
    394   EXPECT_EQ(1, listener.copy);
    395   EXPECT_EQ(0, listener.move);
    396   optional<Listenable> move(std::move(original));
    397   EXPECT_EQ(1, listener.construct0);
    398   EXPECT_EQ(1, listener.copy);
    399   EXPECT_EQ(1, listener.move);
    400 }
    401 
    402 TEST(optionalTest, ListInit) {
    403   StructorListener listener;
    404   Listenable::listener = &listener;
    405   optional<Listenable> listinit1(in_place, {1});
    406   optional<Listenable> listinit2(in_place, {1, 2});
    407   EXPECT_EQ(2, listener.listinit);
    408 }
    409 
    410 TEST(optionalTest, AssignFromNullopt) {
    411   optional<int> opt(1);
    412   opt = nullopt;
    413   EXPECT_FALSE(!!opt);
    414 
    415   StructorListener listener;
    416   Listenable::listener = &listener;
    417   optional<Listenable> opt1(in_place);
    418   opt1 = nullopt;
    419   EXPECT_FALSE(opt1);
    420   EXPECT_EQ(1, listener.construct0);
    421   EXPECT_EQ(1, listener.destruct);
    422 
    423   EXPECT_TRUE((std::is_nothrow_assignable<optional<int>, nullopt_t>::value));
    424   EXPECT_TRUE(
    425       (std::is_nothrow_assignable<optional<Listenable>, nullopt_t>::value));
    426 }
    427 
    428 TEST(optionalTest, CopyAssignment) {
    429   const optional<int> empty, opt1 = 1, opt2 = 2;
    430   optional<int> empty_to_opt1, opt1_to_opt2, opt2_to_empty;
    431 
    432   EXPECT_FALSE(!!empty_to_opt1);
    433   empty_to_opt1 = empty;
    434   EXPECT_FALSE(!!empty_to_opt1);
    435   empty_to_opt1 = opt1;
    436   EXPECT_TRUE(!!empty_to_opt1);
    437   EXPECT_EQ(1, empty_to_opt1.value());
    438 
    439   EXPECT_FALSE(!!opt1_to_opt2);
    440   opt1_to_opt2 = opt1;
    441   EXPECT_TRUE(!!opt1_to_opt2);
    442   EXPECT_EQ(1, opt1_to_opt2.value());
    443   opt1_to_opt2 = opt2;
    444   EXPECT_TRUE(!!opt1_to_opt2);
    445   EXPECT_EQ(2, opt1_to_opt2.value());
    446 
    447   EXPECT_FALSE(!!opt2_to_empty);
    448   opt2_to_empty = opt2;
    449   EXPECT_TRUE(!!opt2_to_empty);
    450   EXPECT_EQ(2, opt2_to_empty.value());
    451   opt2_to_empty = empty;
    452   EXPECT_FALSE(!!opt2_to_empty);
    453 
    454   EXPECT_TRUE(std::is_copy_assignable<optional<Copyable>>::value);
    455   EXPECT_FALSE(std::is_copy_assignable<optional<MoveableThrow>>::value);
    456   EXPECT_FALSE(std::is_copy_assignable<optional<MoveableNoThrow>>::value);
    457   EXPECT_FALSE(std::is_copy_assignable<optional<NonMovable>>::value);
    458 }
    459 
    460 TEST(optionalTest, MoveAssignment) {
    461   StructorListener listener;
    462   Listenable::listener = &listener;
    463 
    464   optional<Listenable> empty1, empty2, set1(in_place), set2(in_place);
    465   EXPECT_EQ(2, listener.construct0);
    466   optional<Listenable> empty_to_empty, empty_to_set, set_to_empty(in_place),
    467       set_to_set(in_place);
    468   EXPECT_EQ(4, listener.construct0);
    469   empty_to_empty = std::move(empty1);
    470   empty_to_set = std::move(set1);
    471   set_to_empty = std::move(empty2);
    472   set_to_set = std::move(set2);
    473   EXPECT_EQ(0, listener.copy);
    474   EXPECT_EQ(1, listener.move);
    475   EXPECT_EQ(1, listener.destruct);
    476   EXPECT_EQ(1, listener.move_assign);
    477 
    478   EXPECT_TRUE(std::is_move_assignable<optional<Copyable>>::value);
    479   EXPECT_TRUE(std::is_move_assignable<optional<MoveableThrow>>::value);
    480   EXPECT_TRUE(std::is_move_assignable<optional<MoveableNoThrow>>::value);
    481   EXPECT_FALSE(std::is_move_assignable<optional<NonMovable>>::value);
    482 
    483   EXPECT_FALSE(std::is_nothrow_move_assignable<optional<MoveableThrow>>::value);
    484   EXPECT_TRUE(
    485       std::is_nothrow_move_assignable<optional<MoveableNoThrow>>::value);
    486 }
    487 
    488 struct NoConvertToOptional {
    489   // disable implicit conversion from const NoConvertToOptional&
    490   // to optional<NoConvertToOptional>.
    491   NoConvertToOptional(const NoConvertToOptional&) = delete;
    492 };
    493 
    494 struct CopyConvert {
    495   CopyConvert(const NoConvertToOptional&);
    496   CopyConvert& operator=(const CopyConvert&) = delete;
    497   CopyConvert& operator=(const NoConvertToOptional&);
    498 };
    499 
    500 struct CopyConvertFromOptional {
    501   CopyConvertFromOptional(const NoConvertToOptional&);
    502   CopyConvertFromOptional(const optional<NoConvertToOptional>&);
    503   CopyConvertFromOptional& operator=(const CopyConvertFromOptional&) = delete;
    504   CopyConvertFromOptional& operator=(const NoConvertToOptional&);
    505   CopyConvertFromOptional& operator=(const optional<NoConvertToOptional>&);
    506 };
    507 
    508 struct MoveConvert {
    509   MoveConvert(NoConvertToOptional&&);
    510   MoveConvert& operator=(const MoveConvert&) = delete;
    511   MoveConvert& operator=(NoConvertToOptional&&);
    512 };
    513 
    514 struct MoveConvertFromOptional {
    515   MoveConvertFromOptional(NoConvertToOptional&&);
    516   MoveConvertFromOptional(optional<NoConvertToOptional>&&);
    517   MoveConvertFromOptional& operator=(const MoveConvertFromOptional&) = delete;
    518   MoveConvertFromOptional& operator=(NoConvertToOptional&&);
    519   MoveConvertFromOptional& operator=(optional<NoConvertToOptional>&&);
    520 };
    521 
    522 // template <class U = T> optional<T>& operator=(U&& v);
    523 TEST(optionalTest, ValueAssignment) {
    524   optional<int> opt;
    525   EXPECT_FALSE(!!opt);
    526   opt = 42;
    527   EXPECT_TRUE(!!opt);
    528   EXPECT_EQ(42, opt.value());
    529   opt = nullopt;
    530   EXPECT_FALSE(!!opt);
    531   opt = 42;
    532   EXPECT_TRUE(!!opt);
    533   EXPECT_EQ(42, opt.value());
    534   opt = 43;
    535   EXPECT_TRUE(!!opt);
    536   EXPECT_EQ(43, opt.value());
    537   opt = {};  // this should clear optional
    538   EXPECT_FALSE(!!opt);
    539 
    540   opt = {44};
    541   EXPECT_TRUE(!!opt);
    542   EXPECT_EQ(44, opt.value());
    543 
    544   // U = const NoConvertToOptional&
    545   EXPECT_TRUE((std::is_assignable<optional<CopyConvert>&,
    546                                   const NoConvertToOptional&>::value));
    547   // U = const optional<NoConvertToOptional>&
    548   EXPECT_TRUE((std::is_assignable<optional<CopyConvertFromOptional>&,
    549                                   const NoConvertToOptional&>::value));
    550   // U = const NoConvertToOptional& triggers SFINAE because
    551   // std::is_constructible_v<MoveConvert, const NoConvertToOptional&> is false
    552   EXPECT_FALSE((std::is_assignable<optional<MoveConvert>&,
    553                                    const NoConvertToOptional&>::value));
    554   // U = NoConvertToOptional
    555   EXPECT_TRUE((std::is_assignable<optional<MoveConvert>&,
    556                                   NoConvertToOptional&&>::value));
    557   // U = const NoConvertToOptional& triggers SFINAE because
    558   // std::is_constructible_v<MoveConvertFromOptional, const
    559   // NoConvertToOptional&> is false
    560   EXPECT_FALSE((std::is_assignable<optional<MoveConvertFromOptional>&,
    561                                    const NoConvertToOptional&>::value));
    562   // U = NoConvertToOptional
    563   EXPECT_TRUE((std::is_assignable<optional<MoveConvertFromOptional>&,
    564                                   NoConvertToOptional&&>::value));
    565   // U = const optional<NoConvertToOptional>&
    566   EXPECT_TRUE(
    567       (std::is_assignable<optional<CopyConvertFromOptional>&,
    568                           const optional<NoConvertToOptional>&>::value));
    569   // U = optional<NoConvertToOptional>
    570   EXPECT_TRUE((std::is_assignable<optional<MoveConvertFromOptional>&,
    571                                   optional<NoConvertToOptional>&&>::value));
    572 }
    573 
    574 // template <class U> optional<T>& operator=(const optional<U>& rhs);
    575 // template <class U> optional<T>& operator=(optional<U>&& rhs);
    576 TEST(optionalTest, ConvertingAssignment) {
    577   optional<int> opt_i;
    578   optional<char> opt_c('c');
    579   opt_i = opt_c;
    580   EXPECT_TRUE(!!opt_i);
    581   EXPECT_EQ(*opt_c, *opt_i);
    582   opt_i = optional<char>();
    583   EXPECT_FALSE(!!opt_i);
    584   opt_i = optional<char>('d');
    585   EXPECT_TRUE(!!opt_i);
    586   EXPECT_EQ('d', *opt_i);
    587 
    588   optional<string> opt_str;
    589   optional<const char*> opt_cstr("abc");
    590   opt_str = opt_cstr;
    591   EXPECT_TRUE(!!opt_str);
    592   EXPECT_EQ(string("abc"), *opt_str);
    593   opt_str = optional<const char*>();
    594   EXPECT_FALSE(!!opt_str);
    595   opt_str = optional<const char*>("def");
    596   EXPECT_TRUE(!!opt_str);
    597   EXPECT_EQ(string("def"), *opt_str);
    598 
    599   // operator=(const optional<U>&) with U = NoConvertToOptional
    600   EXPECT_TRUE(
    601       (std::is_assignable<optional<CopyConvert>,
    602                           const optional<NoConvertToOptional>&>::value));
    603   // operator=(const optional<U>&) with U = NoConvertToOptional
    604   // triggers SFINAE because
    605   // std::is_constructible_v<MoveConvert, const NoConvertToOptional&> is false
    606   EXPECT_FALSE(
    607       (std::is_assignable<optional<MoveConvert>&,
    608                           const optional<NoConvertToOptional>&>::value));
    609   // operator=(optional<U>&&) with U = NoConvertToOptional
    610   EXPECT_TRUE((std::is_assignable<optional<MoveConvert>&,
    611                                   optional<NoConvertToOptional>&&>::value));
    612   // operator=(const optional<U>&) with U = NoConvertToOptional triggers SFINAE
    613   // because std::is_constructible_v<MoveConvertFromOptional,
    614   // const NoConvertToOptional&> is false.
    615   // operator=(U&&) with U = const optional<NoConverToOptional>& triggers SFINAE
    616   // because std::is_constructible<MoveConvertFromOptional,
    617   // optional<NoConvertToOptional>&&> is true.
    618   EXPECT_FALSE(
    619       (std::is_assignable<optional<MoveConvertFromOptional>&,
    620                           const optional<NoConvertToOptional>&>::value));
    621 }
    622 
    623 TEST(optionalTest, ResetAndHasValue) {
    624   StructorListener listener;
    625   Listenable::listener = &listener;
    626   optional<Listenable> opt;
    627   EXPECT_FALSE(!!opt);
    628   EXPECT_FALSE(opt.has_value());
    629   opt.emplace();
    630   EXPECT_TRUE(!!opt);
    631   EXPECT_TRUE(opt.has_value());
    632   opt.reset();
    633   EXPECT_FALSE(!!opt);
    634   EXPECT_FALSE(opt.has_value());
    635   EXPECT_EQ(1, listener.destruct);
    636   opt.reset();
    637   EXPECT_FALSE(!!opt);
    638   EXPECT_FALSE(opt.has_value());
    639 
    640   constexpr optional<int> empty;
    641   static_assert(!empty.has_value(), "");
    642   constexpr optional<int> nonempty(1);
    643   static_assert(nonempty.has_value(), "");
    644 }
    645 
    646 TEST(optionalTest, Emplace) {
    647   StructorListener listener;
    648   Listenable::listener = &listener;
    649   optional<Listenable> opt;
    650   EXPECT_FALSE(!!opt);
    651   opt.emplace(1);
    652   EXPECT_TRUE(!!opt);
    653   opt.emplace(1, 2);
    654   EXPECT_EQ(1, listener.construct1);
    655   EXPECT_EQ(1, listener.construct2);
    656   EXPECT_EQ(1, listener.destruct);
    657 }
    658 
    659 TEST(optionalTest, ListEmplace) {
    660   StructorListener listener;
    661   Listenable::listener = &listener;
    662   optional<Listenable> opt;
    663   EXPECT_FALSE(!!opt);
    664   opt.emplace({1});
    665   EXPECT_TRUE(!!opt);
    666   opt.emplace({1, 2});
    667   EXPECT_EQ(2, listener.listinit);
    668   EXPECT_EQ(1, listener.destruct);
    669 }
    670 
    671 TEST(optionalTest, Swap) {
    672   optional<int> opt_empty, opt1 = 1, opt2 = 2;
    673   EXPECT_FALSE(!!opt_empty);
    674   EXPECT_TRUE(!!opt1);
    675   EXPECT_EQ(1, opt1.value());
    676   EXPECT_TRUE(!!opt2);
    677   EXPECT_EQ(2, opt2.value());
    678   swap(opt_empty, opt1);
    679   EXPECT_FALSE(!!opt1);
    680   EXPECT_TRUE(!!opt_empty);
    681   EXPECT_EQ(1, opt_empty.value());
    682   EXPECT_TRUE(!!opt2);
    683   EXPECT_EQ(2, opt2.value());
    684   swap(opt_empty, opt1);
    685   EXPECT_FALSE(!!opt_empty);
    686   EXPECT_TRUE(!!opt1);
    687   EXPECT_EQ(1, opt1.value());
    688   EXPECT_TRUE(!!opt2);
    689   EXPECT_EQ(2, opt2.value());
    690   swap(opt1, opt2);
    691   EXPECT_FALSE(!!opt_empty);
    692   EXPECT_TRUE(!!opt1);
    693   EXPECT_EQ(2, opt1.value());
    694   EXPECT_TRUE(!!opt2);
    695   EXPECT_EQ(1, opt2.value());
    696 
    697   EXPECT_TRUE(noexcept(opt1.swap(opt2)));
    698   EXPECT_TRUE(noexcept(swap(opt1, opt2)));
    699 }
    700 
    701 TEST(optionalTest, PointerStuff) {
    702   optional<string> opt(in_place, "foo");
    703   EXPECT_EQ("foo", *opt);
    704   const auto& opt_const = opt;
    705   EXPECT_EQ("foo", *opt_const);
    706   EXPECT_EQ(opt->size(), 3);
    707   EXPECT_EQ(opt_const->size(), 3);
    708 
    709   constexpr optional<ConstexprType> opt1(1);
    710   static_assert(opt1->x == 1, "");
    711 }
    712 
    713 // gcc has a bug pre 4.9 where it doesn't do correct overload resolution
    714 // between rvalue reference qualified member methods. Skip that test to make
    715 // the build green again when using the old compiler.
    716 #if defined(__GNUC__) && !defined(__clang__)
    717 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9)
    718 #define SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG
    719 #endif
    720 #endif
    721 
    722 TEST(optionalTest, Value) {
    723   using O = optional<string>;
    724   using CO = const optional<string>;
    725   O lvalue(in_place, "lvalue");
    726   CO clvalue(in_place, "clvalue");
    727   EXPECT_EQ("lvalue", lvalue.value());
    728   EXPECT_EQ("clvalue", clvalue.value());
    729   EXPECT_EQ("xvalue", O(in_place, "xvalue").value());
    730 #ifndef SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG
    731   EXPECT_EQ("cxvalue", CO(in_place, "cxvalue").value());
    732   EXPECT_EQ("&", TypeQuals(lvalue.value()));
    733   EXPECT_EQ("c&", TypeQuals(clvalue.value()));
    734   EXPECT_EQ("&&", TypeQuals(O(in_place, "xvalue").value()));
    735   EXPECT_EQ("c&&", TypeQuals(CO(in_place, "cxvalue").value()));
    736 #endif
    737 }
    738 
    739 TEST(optionalTest, DerefOperator) {
    740   using O = optional<string>;
    741   using CO = const optional<string>;
    742   O lvalue(in_place, "lvalue");
    743   CO clvalue(in_place, "clvalue");
    744   EXPECT_EQ("lvalue", *lvalue);
    745   EXPECT_EQ("clvalue", *clvalue);
    746   EXPECT_EQ("xvalue", *O(in_place, "xvalue"));
    747 #ifndef SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG
    748   EXPECT_EQ("cxvalue", *CO(in_place, "cxvalue"));
    749   EXPECT_EQ("&", TypeQuals(*lvalue));
    750   EXPECT_EQ("c&", TypeQuals(*clvalue));
    751   EXPECT_EQ("&&", TypeQuals(*O(in_place, "xvalue")));
    752   EXPECT_EQ("c&&", TypeQuals(*CO(in_place, "cxvalue")));
    753 #endif
    754 
    755   constexpr optional<int> opt1(1);
    756   static_assert(*opt1 == 1, "");
    757 
    758 #if !defined(SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG) && \
    759     !defined(SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
    760   using COI = const optional<int>;
    761   static_assert(*COI(2) == 2, "");
    762 #endif
    763 }
    764 
    765 TEST(optionalTest, ValueOr) {
    766   optional<double> opt_empty, opt_set = 1.2;
    767   EXPECT_EQ(42.0, opt_empty.value_or(42));
    768   EXPECT_EQ(1.2, opt_set.value_or(42));
    769   EXPECT_EQ(42.0, optional<double>().value_or(42));
    770   EXPECT_EQ(1.2, optional<double>(1.2).value_or(42));
    771 
    772 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG
    773   constexpr optional<double> copt_empty;
    774   static_assert(42.0 == copt_empty.value_or(42), "");
    775 
    776   constexpr optional<double> copt_set = {1.2};
    777   static_assert(1.2 == copt_set.value_or(42), "");
    778 
    779   using COD = const optional<double>;
    780   static_assert(42.0 == COD().value_or(42), "");
    781   static_assert(1.2 == COD(1.2).value_or(42), "");
    782 #endif
    783 }
    784 
    785 // make_optional cannot be constexpr until C++17
    786 TEST(optionalTest, make_optional) {
    787   auto opt_int = make_optional(42);
    788   EXPECT_TRUE((std::is_same<decltype(opt_int), optional<int>>::value));
    789   EXPECT_EQ(42, opt_int);
    790 
    791   StructorListener listener;
    792   Listenable::listener = &listener;
    793 
    794   optional<Listenable> opt0 = make_optional<Listenable>();
    795   EXPECT_EQ(1, listener.construct0);
    796   optional<Listenable> opt1 = make_optional<Listenable>(1);
    797   EXPECT_EQ(1, listener.construct1);
    798   optional<Listenable> opt2 = make_optional<Listenable>(1, 2);
    799   EXPECT_EQ(1, listener.construct2);
    800   optional<Listenable> opt3 = make_optional<Listenable>({1});
    801   optional<Listenable> opt4 = make_optional<Listenable>({1, 2});
    802   EXPECT_EQ(2, listener.listinit);
    803 }
    804 
    805 TEST(optionalTest, Comparisons) {
    806   optional<int> ae, be, a2 = 2, b2 = 2, a4 = 4, b4 = 4;
    807 
    808 #define optionalTest_Comparisons_EXPECT_LESS(x, y) \
    809   EXPECT_FALSE((x) == (y));                        \
    810   EXPECT_TRUE((x) != (y));                         \
    811   EXPECT_TRUE((x) < (y));                          \
    812   EXPECT_FALSE((x) > (y));                         \
    813   EXPECT_TRUE((x) <= (y));                         \
    814   EXPECT_FALSE((x) >= (y));
    815 
    816 #define optionalTest_Comparisons_EXPECT_SAME(x, y) \
    817   EXPECT_TRUE((x) == (y));                         \
    818   EXPECT_FALSE((x) != (y));                        \
    819   EXPECT_FALSE((x) < (y));                         \
    820   EXPECT_FALSE((x) > (y));                         \
    821   EXPECT_TRUE((x) <= (y));                         \
    822   EXPECT_TRUE((x) >= (y));
    823 
    824 #define optionalTest_Comparisons_EXPECT_GREATER(x, y) \
    825   EXPECT_FALSE((x) == (y));                           \
    826   EXPECT_TRUE((x) != (y));                            \
    827   EXPECT_FALSE((x) < (y));                            \
    828   EXPECT_TRUE((x) > (y));                             \
    829   EXPECT_FALSE((x) <= (y));                           \
    830   EXPECT_TRUE((x) >= (y));
    831 
    832   // LHS: nullopt, ae, a2, 3, a4
    833   // RHS: nullopt, be, b2, 3, b4
    834 
    835   // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(nullopt,nullopt);
    836   optionalTest_Comparisons_EXPECT_SAME(nullopt, be);
    837   optionalTest_Comparisons_EXPECT_LESS(nullopt, b2);
    838   // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(nullopt,3);
    839   optionalTest_Comparisons_EXPECT_LESS(nullopt, b4);
    840 
    841   optionalTest_Comparisons_EXPECT_SAME(ae, nullopt);
    842   optionalTest_Comparisons_EXPECT_SAME(ae, be);
    843   optionalTest_Comparisons_EXPECT_LESS(ae, b2);
    844   optionalTest_Comparisons_EXPECT_LESS(ae, 3);
    845   optionalTest_Comparisons_EXPECT_LESS(ae, b4);
    846 
    847   optionalTest_Comparisons_EXPECT_GREATER(a2, nullopt);
    848   optionalTest_Comparisons_EXPECT_GREATER(a2, be);
    849   optionalTest_Comparisons_EXPECT_SAME(a2, b2);
    850   optionalTest_Comparisons_EXPECT_LESS(a2, 3);
    851   optionalTest_Comparisons_EXPECT_LESS(a2, b4);
    852 
    853   // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(3,nullopt);
    854   optionalTest_Comparisons_EXPECT_GREATER(3, be);
    855   optionalTest_Comparisons_EXPECT_GREATER(3, b2);
    856   optionalTest_Comparisons_EXPECT_SAME(3, 3);
    857   optionalTest_Comparisons_EXPECT_LESS(3, b4);
    858 
    859   optionalTest_Comparisons_EXPECT_GREATER(a4, nullopt);
    860   optionalTest_Comparisons_EXPECT_GREATER(a4, be);
    861   optionalTest_Comparisons_EXPECT_GREATER(a4, b2);
    862   optionalTest_Comparisons_EXPECT_GREATER(a4, 3);
    863   optionalTest_Comparisons_EXPECT_SAME(a4, b4);
    864 }
    865 
    866 TEST(optionalTest, SwapRegression) {
    867   StructorListener listener;
    868   Listenable::listener = &listener;
    869 
    870   {
    871     optional<Listenable> a;
    872     optional<Listenable> b(in_place);
    873     a.swap(b);
    874   }
    875 
    876   EXPECT_EQ(1, listener.construct0);
    877   EXPECT_EQ(1, listener.move);
    878   EXPECT_EQ(2, listener.destruct);
    879 
    880   {
    881     optional<Listenable> a(in_place);
    882     optional<Listenable> b;
    883     a.swap(b);
    884   }
    885 
    886   EXPECT_EQ(2, listener.construct0);
    887   EXPECT_EQ(2, listener.move);
    888   EXPECT_EQ(4, listener.destruct);
    889 }
    890 
    891 TEST(optionalTest, BigStringLeakCheck) {
    892   constexpr size_t n = 1 << 16;
    893 
    894   using OS = optional<string>;
    895 
    896   OS a;
    897   OS b = nullopt;
    898   OS c = string(n, 'c');
    899   string sd(n, 'd');
    900   OS d = sd;
    901   OS e(in_place, n, 'e');
    902   OS f;
    903   f.emplace(n, 'f');
    904 
    905   OS ca(a);
    906   OS cb(b);
    907   OS cc(c);
    908   OS cd(d);
    909   OS ce(e);
    910 
    911   OS oa;
    912   OS ob = nullopt;
    913   OS oc = string(n, 'c');
    914   string sod(n, 'd');
    915   OS od = sod;
    916   OS oe(in_place, n, 'e');
    917   OS of;
    918   of.emplace(n, 'f');
    919 
    920   OS ma(std::move(oa));
    921   OS mb(std::move(ob));
    922   OS mc(std::move(oc));
    923   OS md(std::move(od));
    924   OS me(std::move(oe));
    925   OS mf(std::move(of));
    926 
    927   OS aa1;
    928   OS ab1 = nullopt;
    929   OS ac1 = string(n, 'c');
    930   string sad1(n, 'd');
    931   OS ad1 = sad1;
    932   OS ae1(in_place, n, 'e');
    933   OS af1;
    934   af1.emplace(n, 'f');
    935 
    936   OS aa2;
    937   OS ab2 = nullopt;
    938   OS ac2 = string(n, 'c');
    939   string sad2(n, 'd');
    940   OS ad2 = sad2;
    941   OS ae2(in_place, n, 'e');
    942   OS af2;
    943   af2.emplace(n, 'f');
    944 
    945   aa1 = af2;
    946   ab1 = ae2;
    947   ac1 = ad2;
    948   ad1 = ac2;
    949   ae1 = ab2;
    950   af1 = aa2;
    951 
    952   OS aa3;
    953   OS ab3 = nullopt;
    954   OS ac3 = string(n, 'c');
    955   string sad3(n, 'd');
    956   OS ad3 = sad3;
    957   OS ae3(in_place, n, 'e');
    958   OS af3;
    959   af3.emplace(n, 'f');
    960 
    961   aa3 = nullopt;
    962   ab3 = nullopt;
    963   ac3 = nullopt;
    964   ad3 = nullopt;
    965   ae3 = nullopt;
    966   af3 = nullopt;
    967 
    968   OS aa4;
    969   OS ab4 = nullopt;
    970   OS ac4 = string(n, 'c');
    971   string sad4(n, 'd');
    972   OS ad4 = sad4;
    973   OS ae4(in_place, n, 'e');
    974   OS af4;
    975   af4.emplace(n, 'f');
    976 
    977   aa4 = OS(in_place, n, 'a');
    978   ab4 = OS(in_place, n, 'b');
    979   ac4 = OS(in_place, n, 'c');
    980   ad4 = OS(in_place, n, 'd');
    981   ae4 = OS(in_place, n, 'e');
    982   af4 = OS(in_place, n, 'f');
    983 
    984   OS aa5;
    985   OS ab5 = nullopt;
    986   OS ac5 = string(n, 'c');
    987   string sad5(n, 'd');
    988   OS ad5 = sad5;
    989   OS ae5(in_place, n, 'e');
    990   OS af5;
    991   af5.emplace(n, 'f');
    992 
    993   string saa5(n, 'a');
    994   string sab5(n, 'a');
    995   string sac5(n, 'a');
    996   string sad52(n, 'a');
    997   string sae5(n, 'a');
    998   string saf5(n, 'a');
    999 
   1000   aa5 = saa5;
   1001   ab5 = sab5;
   1002   ac5 = sac5;
   1003   ad5 = sad52;
   1004   ae5 = sae5;
   1005   af5 = saf5;
   1006 
   1007   OS aa6;
   1008   OS ab6 = nullopt;
   1009   OS ac6 = string(n, 'c');
   1010   string sad6(n, 'd');
   1011   OS ad6 = sad6;
   1012   OS ae6(in_place, n, 'e');
   1013   OS af6;
   1014   af6.emplace(n, 'f');
   1015 
   1016   aa6 = string(n, 'a');
   1017   ab6 = string(n, 'b');
   1018   ac6 = string(n, 'c');
   1019   ad6 = string(n, 'd');
   1020   ae6 = string(n, 'e');
   1021   af6 = string(n, 'f');
   1022 
   1023   OS aa7;
   1024   OS ab7 = nullopt;
   1025   OS ac7 = string(n, 'c');
   1026   string sad7(n, 'd');
   1027   OS ad7 = sad7;
   1028   OS ae7(in_place, n, 'e');
   1029   OS af7;
   1030   af7.emplace(n, 'f');
   1031 
   1032   aa7.emplace(n, 'A');
   1033   ab7.emplace(n, 'B');
   1034   ac7.emplace(n, 'C');
   1035   ad7.emplace(n, 'D');
   1036   ae7.emplace(n, 'E');
   1037   af7.emplace(n, 'F');
   1038 }
   1039 
   1040 TEST(optionalTest, MoveAssignRegression) {
   1041   StructorListener listener;
   1042   Listenable::listener = &listener;
   1043 
   1044   {
   1045     optional<Listenable> a;
   1046     Listenable b;
   1047     a = std::move(b);
   1048   }
   1049 
   1050   EXPECT_EQ(1, listener.construct0);
   1051   EXPECT_EQ(1, listener.move);
   1052   EXPECT_EQ(2, listener.destruct);
   1053 }
   1054 
   1055 TEST(optionalTest, ValueType) {
   1056   EXPECT_TRUE((std::is_same<optional<int>::value_type, int>::value));
   1057   EXPECT_TRUE((std::is_same<optional<string>::value_type, string>::value));
   1058   EXPECT_FALSE((std::is_same<optional<int>::value_type, nullopt_t>::value));
   1059 }
   1060 
   1061 TEST(optionalTest, Hash) {
   1062   std::hash<optional<int>> hash;
   1063   std::set<size_t> hashcodes;
   1064   hashcodes.insert(hash(nullopt));
   1065   for (int i = 0; i < 100; ++i) {
   1066     hashcodes.insert(hash(i));
   1067   }
   1068   EXPECT_GT(hashcodes.size(), 90);
   1069 }
   1070 
   1071 struct MoveMeNoThrow {
   1072   MoveMeNoThrow() : x(0) {}
   1073   MoveMeNoThrow(const MoveMeNoThrow& other) : x(other.x) {
   1074     LOG(FATAL) << "Should not be called.";
   1075   }
   1076   MoveMeNoThrow(MoveMeNoThrow&& other) noexcept : x(other.x) {}
   1077   int x;
   1078 };
   1079 
   1080 struct MoveMeThrow {
   1081   MoveMeThrow() : x(0) {}
   1082   MoveMeThrow(const MoveMeThrow& other) : x(other.x) {}
   1083   MoveMeThrow(MoveMeThrow&& other) : x(other.x) {}
   1084   int x;
   1085 };
   1086 
   1087 TEST(optionalTest, NoExcept) {
   1088   static_assert(
   1089       std::is_nothrow_move_constructible<optional<MoveMeNoThrow>>::value, "");
   1090   static_assert(
   1091       !std::is_nothrow_move_constructible<optional<MoveMeThrow>>::value, "");
   1092   std::vector<optional<MoveMeNoThrow>> v;
   1093   v.reserve(10);
   1094   for (int i = 0; i < 10; ++i) v.emplace_back();
   1095 }
   1096 
   1097 }  // namespace
   1098 }  // namespace tensorflow
   1099