brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · ddb9ffc Raw
340 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// <optional>11 12// template <class U> optional<T>& operator=(U&& v);13 14#include <optional>15#include <type_traits>16#include <cassert>17#include <memory>18 19#include "test_macros.h"20#include "archetypes.h"21 22using std::optional;23 24struct ThrowAssign {25  static int dtor_called;26  ThrowAssign() = default;27  ThrowAssign(int) { TEST_THROW(42); }28  ThrowAssign& operator=(int) {29      TEST_THROW(42);30  }31  ~ThrowAssign() { ++dtor_called; }32};33int ThrowAssign::dtor_called = 0;34 35template <class T, class Arg = T, bool Expect = true>36void assert_assignable() {37    static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, "");38    static_assert(!std::is_assignable<const optional<T>&, Arg>::value, "");39}40 41struct MismatchType {42  explicit MismatchType(int) {}43  explicit MismatchType(char*) {}44  explicit MismatchType(int*) = delete;45  MismatchType& operator=(int) { return *this; }46  MismatchType& operator=(int*) { return *this; }47  MismatchType& operator=(char*) = delete;48};49 50struct FromOptionalType {51  using Opt = std::optional<FromOptionalType>;52  FromOptionalType() = default;53  FromOptionalType(FromOptionalType const&) = delete;54  template <class Dummy = void>55  constexpr FromOptionalType(Opt&) { Dummy::BARK; }56  template <class Dummy = void>57  constexpr FromOptionalType& operator=(Opt&) { Dummy::BARK; return *this; }58};59 60void test_sfinae() {61    using I = TestTypes::TestType;62    using E = ExplicitTestTypes::TestType;63    assert_assignable<int>();64    assert_assignable<int, int&>();65    assert_assignable<int, int const&>();66    // Implicit test type67    assert_assignable<I, I const&>();68    assert_assignable<I, I&&>();69    assert_assignable<I, int>();70    assert_assignable<I, void*, false>();71    // Explicit test type72    assert_assignable<E, E const&>();73    assert_assignable<E, E &&>();74    assert_assignable<E, int>();75    assert_assignable<E, void*, false>();76    // Mismatch type77    assert_assignable<MismatchType, int>();78    assert_assignable<MismatchType, int*, false>();79    assert_assignable<MismatchType, char*, false>();80    // Type constructible from optional81    assert_assignable<FromOptionalType, std::optional<FromOptionalType>&, false>();82}83 84void test_with_test_type()85{86    using T = TestTypes::TestType;87    T::reset();88    { // to empty89        optional<T> opt;90        opt = 3;91        assert(T::alive == 1);92        assert(T::constructed == 1);93        assert(T::value_constructed == 1);94        assert(T::assigned == 0);95        assert(T::destroyed == 0);96        assert(static_cast<bool>(opt) == true);97        assert(*opt == T(3));98    }99    { // to existing100        optional<T> opt(42);101        T::reset_constructors();102        opt = 3;103        assert(T::alive == 1);104        assert(T::constructed == 0);105        assert(T::assigned == 1);106        assert(T::value_assigned == 1);107        assert(T::destroyed == 0);108        assert(static_cast<bool>(opt) == true);109        assert(*opt == T(3));110    }111    { // test default argument112        optional<T> opt;113        T::reset_constructors();114        opt = {1, 2};115        assert(T::alive == 1);116        assert(T::constructed == 2);117        assert(T::value_constructed == 1);118        assert(T::move_constructed == 1);119        assert(T::assigned == 0);120        assert(T::destroyed == 1);121        assert(static_cast<bool>(opt) == true);122        assert(*opt == T(1, 2));123    }124    { // test default argument125        optional<T> opt(42);126        T::reset_constructors();127        opt = {1, 2};128        assert(T::alive == 1);129        assert(T::constructed == 1);130        assert(T::value_constructed == 1);131        assert(T::assigned == 1);132        assert(T::move_assigned == 1);133        assert(T::destroyed == 1);134        assert(static_cast<bool>(opt) == true);135        assert(*opt == T(1, 2));136    }137    { // test default argument138        optional<T> opt;139        T::reset_constructors();140        opt = {1};141        assert(T::alive == 1);142        assert(T::constructed == 2);143        assert(T::value_constructed == 1);144        assert(T::move_constructed == 1);145        assert(T::assigned == 0);146        assert(T::destroyed == 1);147        assert(static_cast<bool>(opt) == true);148        assert(*opt == T(1));149    }150    { // test default argument151        optional<T> opt(42);152        T::reset_constructors();153        opt = {};154        assert(static_cast<bool>(opt) == false);155        assert(T::alive == 0);156        assert(T::constructed == 0);157        assert(T::assigned == 0);158        assert(T::destroyed == 1);159    }160}161 162template <class T, class Value = int>163void test_with_type() {164    { // to empty165        optional<T> opt;166        opt = Value(3);167        assert(static_cast<bool>(opt) == true);168        assert(*opt == T(3));169    }170    { // to existing171        optional<T> opt(Value(42));172        opt = Value(3);173        assert(static_cast<bool>(opt) == true);174        assert(*opt == T(3));175    }176    { // test const177        optional<T> opt(Value(42));178        const T t(Value(3));179        opt = t;180        assert(static_cast<bool>(opt) == true);181        assert(*opt == T(3));182    }183    { // test default argument184        optional<T> opt;185        opt = {Value(1)};186        assert(static_cast<bool>(opt) == true);187        assert(*opt == T(1));188    }189    { // test default argument190        optional<T> opt(Value(42));191        opt = {};192        assert(static_cast<bool>(opt) == false);193    }194}195 196template <class T>197void test_with_type_multi() {198    test_with_type<T>();199    { // test default argument200        optional<T> opt;201        opt = {1, 2};202        assert(static_cast<bool>(opt) == true);203        assert(*opt == T(1, 2));204    }205    { // test default argument206        optional<T> opt(42);207        opt = {1, 2};208        assert(static_cast<bool>(opt) == true);209        assert(*opt == T(1, 2));210    }211}212 213void test_throws()214{215#ifndef TEST_HAS_NO_EXCEPTIONS216    using T = ThrowAssign;217    {218        optional<T> opt;219        try {220            opt = 42;221            assert(false);222        } catch (int) {}223        assert(static_cast<bool>(opt) == false);224    }225    assert(T::dtor_called == 0);226    {227        T::dtor_called = 0;228        optional<T> opt(std::in_place);229        try {230            opt = 42;231            assert(false);232        } catch (int) {}233        assert(static_cast<bool>(opt) == true);234        assert(T::dtor_called == 0);235    }236    assert(T::dtor_called == 1);237#endif238}239 240enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 };241 242using Fn = void(*)();243 244// https://llvm.org/PR38638245template <class T>246constexpr T pr38638(T v)247{248  std::optional<T> o;249  o = v;250  return *o + 2;251}252 253#if TEST_STD_VER >= 26254 255template <typename T, std::remove_reference_t<T> _Val>256constexpr void test_with_ref() {257  T t{_Val};258  { // to empty259    optional<T&> opt;260    opt = t;261    assert(static_cast<bool>(opt) == true);262    assert(*opt == t);263  }264  { // to existing265    optional<T&> opt{t};266    opt = t;267    assert(static_cast<bool>(opt) == true);268    assert(*opt == t);269  }270  { // test default argument271    optional<T&> opt;272    opt = {t};273    assert(static_cast<bool>(opt) == true);274    assert(*opt == t);275  }276  { // test default argument277    optional<T&> opt{t};278    opt = {};279    assert(static_cast<bool>(opt) == false);280  }281  // test two objects, make sure that the optional only changes what it holds a reference to282  {283    T t2{_Val};284    optional<T&> opt{t};285    opt = t2;286 287    assert(std::addressof(*opt) != std::addressof(t));288    assert(std::addressof(*opt) == std::addressof(t2));289  }290  // test that reassigning the reference for an optional<T&> doesn't affect the objet it's holding a reference to291  {292    int i = -1;293    int j = 2;294    optional<int&> opt{i};295    opt = j;296 297    assert(i == -1);298    assert(std::addressof(*opt) != std::addressof(i));299    assert(std::addressof(*opt) == std::addressof(j));300    assert(*opt == 2);301  }302}303#endif304 305int main(int, char**)306{307    test_sfinae();308    // Test with instrumented type309    test_with_test_type();310    // Test with various scalar types311    test_with_type<int>();312    test_with_type<MyEnum, MyEnum>();313    test_with_type<int, MyEnum>();314    test_with_type<Fn, Fn>();315    // Test types with multi argument constructors316    test_with_type_multi<ConstexprTestTypes::TestType>();317    test_with_type_multi<TrivialTestTypes::TestType>();318    // Test move only types319    {320        optional<std::unique_ptr<int>> opt;321        opt = std::unique_ptr<int>(new int(3));322        assert(static_cast<bool>(opt) == true);323        assert(**opt == 3);324    }325    {326        optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2)));327        opt = std::unique_ptr<int>(new int(3));328        assert(static_cast<bool>(opt) == true);329        assert(**opt == 3);330    }331    test_throws();332 333    static_assert(pr38638(3) == 5, "");334 335#if TEST_STD_VER >= 26336    test_with_ref<int, 3>();337#endif338    return 0;339}340