brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 583debc Raw
216 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// <optional>12 13// constexpr optional(optional<T>&& rhs);14 15#include <cassert>16#include <optional>17#include <type_traits>18 19#include "test_macros.h"20#include "archetypes.h"21 22using std::optional;23 24template <class T, class... InitArgs>25void test(InitArgs&&... args) {26  const optional<T> orig(std::forward<InitArgs>(args)...);27  optional<T> rhs(orig);28  bool rhs_engaged = static_cast<bool>(rhs);29  optional<T> lhs  = std::move(rhs);30  assert(static_cast<bool>(lhs) == rhs_engaged);31  if (rhs_engaged)32    assert(*lhs == *orig);33}34 35template <class T, class... InitArgs>36constexpr bool constexpr_test(InitArgs&&... args) {37  static_assert(std::is_trivially_copy_constructible_v<T>, ""); // requirement38  const optional<T> orig(std::forward<InitArgs>(args)...);39  optional<T> rhs(orig);40  optional<T> lhs = std::move(rhs);41  return (lhs.has_value() == orig.has_value()) && (lhs.has_value() ? *lhs == *orig : true);42}43 44void test_throwing_ctor() {45#ifndef TEST_HAS_NO_EXCEPTIONS46  struct Z {47    Z() : count(0) {}48    Z(Z&& o) : count(o.count + 1) {49      if (count == 2)50        throw 6;51    }52    int count;53  };54  Z z;55  optional<Z> rhs(std::move(z));56  try {57    optional<Z> lhs(std::move(rhs));58    assert(false);59  } catch (int i) {60    assert(i == 6);61  }62#endif63}64 65template <class T, class... InitArgs>66void test_ref(InitArgs&&... args) {67  optional<T> rhs(std::forward<InitArgs>(args)...);68  bool rhs_engaged = static_cast<bool>(rhs);69  optional<T> lhs  = std::move(rhs);70  assert(static_cast<bool>(lhs) == rhs_engaged);71  if (rhs_engaged)72    assert(&(*lhs) == &(*rhs));73}74 75void test_reference_extension() {76#if TEST_STD_VER >= 2677  using T = TestTypes::TestType;78  T::reset();79  {80    T t;81    T::reset_constructors();82    test_ref<T&>();83    test_ref<T&>(t);84    assert(T::alive == 1);85    assert(T::constructed == 0);86    assert(T::assigned == 0);87    assert(T::destroyed == 0);88  }89  assert(T::destroyed == 1);90  assert(T::alive == 0);91  {92    T t;93    const T& ct = t;94    T::reset_constructors();95    test_ref<T const&>();96    test_ref<T const&>(t);97    test_ref<T const&>(ct);98    assert(T::alive == 1);99    assert(T::constructed == 0);100    assert(T::assigned == 0);101    assert(T::destroyed == 0);102  }103  assert(T::alive == 0);104  assert(T::destroyed == 1);105#  if 0 // FIXME: optional<T&&> is not allowed.106  {107    T t;108    T::reset_constructors();109    test_ref<T&&>();110    test_ref<T&&>(std::move(t));111    assert(T::alive == 1);112    assert(T::constructed == 0);113    assert(T::assigned == 0);114    assert(T::destroyed == 0);115  }116  assert(T::alive == 0);117  assert(T::destroyed == 1);118  {119    T t;120    const T& ct = t;121    T::reset_constructors();122    test_ref<T const&&>();123    test_ref<T const&&>(std::move(t));124    test_ref<T const&&>(std::move(ct));125    assert(T::alive == 1);126    assert(T::constructed == 0);127    assert(T::assigned == 0);128    assert(T::destroyed == 0);129  }130  assert(T::alive == 0);131  assert(T::destroyed == 1);132  {133    static_assert(!std::is_copy_constructible_v<std::optional<T&&>>);134    static_assert(!std::is_copy_constructible_v<std::optional<T const&&>>);135  }136#  endif137#endif138}139 140int main(int, char**) {141  test<int>();142  test<int>(3);143  static_assert(constexpr_test<int>(), "");144  static_assert(constexpr_test<int>(3), "");145 146  {147    optional<const int> o(42);148    optional<const int> o2(std::move(o));149    assert(*o2 == 42);150  }151  {152    using T = TestTypes::TestType;153    T::reset();154    optional<T> rhs;155    assert(T::alive == 0);156    const optional<T> lhs(std::move(rhs));157    assert(lhs.has_value() == false);158    assert(rhs.has_value() == false);159    assert(T::alive == 0);160  }161  TestTypes::TestType::reset();162  {163    using T = TestTypes::TestType;164    T::reset();165    optional<T> rhs(42);166    assert(T::alive == 1);167    assert(T::value_constructed == 1);168    assert(T::move_constructed == 0);169    const optional<T> lhs(std::move(rhs));170    assert(lhs.has_value());171    assert(rhs.has_value());172    assert(lhs.value().value == 42);173    assert(rhs.value().value == -1);174    assert(T::move_constructed == 1);175    assert(T::alive == 2);176  }177  TestTypes::TestType::reset();178  {179    using namespace ConstexprTestTypes;180    test<TestType>();181    test<TestType>(42);182  }183  {184    using namespace TrivialTestTypes;185    test<TestType>();186    test<TestType>(42);187  }188  {189    test_throwing_ctor();190  }191  {192    struct ThrowsMove {193      ThrowsMove() noexcept(false) {}194      ThrowsMove(ThrowsMove const&) noexcept(false) {}195      ThrowsMove(ThrowsMove&&) noexcept(false) {}196    };197    static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, "");198    struct NoThrowMove {199      NoThrowMove() noexcept(false) {}200      NoThrowMove(NoThrowMove const&) noexcept(false) {}201      NoThrowMove(NoThrowMove&&) noexcept(true) {}202    };203    static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, "");204  }205  {206    test_reference_extension();207  }208  {209    constexpr std::optional<int> o1{4};210    constexpr std::optional<int> o2 = std::move(o1);211    static_assert(*o2 == 4, "");212  }213 214  return 0;215}216