brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · 85971e3 Raw
205 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// constexpr optional<T>& operator=(optional<T>&& rhs)13//     noexcept(is_nothrow_move_assignable<T>::value &&14//              is_nothrow_move_constructible<T>::value);15 16#include <optional>17#include <cassert>18#include <type_traits>19#include <utility>20 21#include "test_macros.h"22#include "archetypes.h"23 24using std::optional;25 26struct X27{28    static bool throw_now;29    static int alive;30 31    X() { ++alive; }32    X(X&&)33    {34        if (throw_now)35            TEST_THROW(6);36        ++alive;37    }38 39    X& operator=(X&&)40    {41        if (throw_now)42            TEST_THROW(42);43        return *this;44    }45 46    ~X() { assert(alive > 0); --alive; }47};48 49struct Y {};50 51bool X::throw_now = false;52int X::alive = 0;53 54 55template <class Tp>56constexpr bool assign_empty(optional<Tp>&& lhs) {57    optional<Tp> rhs;58    lhs = std::move(rhs);59    return !lhs.has_value() && !rhs.has_value();60}61 62template <class Tp>63constexpr bool assign_value(optional<Tp>&& lhs) {64    optional<Tp> rhs(101);65    lhs = std::move(rhs);66    return lhs.has_value() && rhs.has_value() && *lhs == Tp{101};67}68 69int main(int, char**)70{71    {72        static_assert(std::is_nothrow_move_assignable<optional<int>>::value, "");73        optional<int> opt;74        constexpr optional<int> opt2;75        opt = std::move(opt2);76        static_assert(static_cast<bool>(opt2) == false, "");77        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));78    }79    {80        optional<int> opt;81        constexpr optional<int> opt2(2);82        opt = std::move(opt2);83        static_assert(static_cast<bool>(opt2) == true, "");84        static_assert(*opt2 == 2, "");85        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));86        assert(*opt == *opt2);87    }88    {89        optional<int> opt(3);90        constexpr optional<int> opt2;91        opt = std::move(opt2);92        static_assert(static_cast<bool>(opt2) == false, "");93        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));94    }95    {96        using T = TestTypes::TestType;97        T::reset();98        optional<T> opt(3);99        optional<T> opt2;100        assert(T::alive == 1);101        opt = std::move(opt2);102        assert(T::alive == 0);103        assert(static_cast<bool>(opt2) == false);104        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));105    }106    {107        optional<int> opt(3);108        constexpr optional<int> opt2(2);109        opt = std::move(opt2);110        static_assert(static_cast<bool>(opt2) == true, "");111        static_assert(*opt2 == 2, "");112        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));113        assert(*opt == *opt2);114    }115    {116        using O = optional<int>;117        static_assert(assign_empty(O{42}));118        static_assert(assign_value(O{42}));119        assert(assign_empty(O{42}));120        assert(assign_value(O{42}));121    }122    {123        using O = optional<TrivialTestTypes::TestType>;124        static_assert(assign_empty(O{42}));125        static_assert(assign_value(O{42}));126        assert(assign_empty(O{42}));127        assert(assign_value(O{42}));128    }129#ifndef TEST_HAS_NO_EXCEPTIONS130    {131        static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");132        X::alive = 0;133        X::throw_now = false;134        optional<X> opt;135        optional<X> opt2(X{});136        assert(X::alive == 1);137        assert(static_cast<bool>(opt2) == true);138        try139        {140            X::throw_now = true;141            opt = std::move(opt2);142            assert(false);143        }144        catch (int i)145        {146            assert(i == 6);147            assert(static_cast<bool>(opt) == false);148        }149        assert(X::alive == 1);150    }151    assert(X::alive == 0);152    {153        static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");154        X::throw_now = false;155        optional<X> opt(X{});156        optional<X> opt2(X{});157        assert(X::alive == 2);158        assert(static_cast<bool>(opt2) == true);159        try160        {161            X::throw_now = true;162            opt = std::move(opt2);163            assert(false);164        }165        catch (int i)166        {167            assert(i == 42);168            assert(static_cast<bool>(opt) == true);169        }170        assert(X::alive == 2);171    }172    assert(X::alive == 0);173#endif // TEST_HAS_NO_EXCEPTIONS174    {175        static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, "");176    }177    {178        struct ThrowsMove {179            ThrowsMove() noexcept {}180            ThrowsMove(ThrowsMove const&) noexcept {}181            ThrowsMove(ThrowsMove &&) noexcept(false) {}182            ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; }183            ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; }184        };185        static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, "");186        struct ThrowsMoveAssign {187            ThrowsMoveAssign() noexcept {}188            ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {}189            ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {}190            ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; }191            ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; }192        };193        static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, "");194        struct NoThrowMove {195            NoThrowMove() noexcept(false) {}196            NoThrowMove(NoThrowMove const&) noexcept(false) {}197            NoThrowMove(NoThrowMove &&) noexcept {}198            NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; }199            NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; }200        };201        static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, "");202    }203    return 0;204}205