brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · 939c766 Raw
208 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// <any>12 13// template <class ValueType>14// any& operator=(ValueType&&);15 16// Test value copy and move assignment.17 18#include <any>19#include <cassert>20 21#include "any_helpers.h"22#include "count_new.h"23#include "test_macros.h"24 25template <class LHS, class RHS>26void test_assign_value() {27    assert(LHS::count == 0);28    assert(RHS::count == 0);29    LHS::reset();30    RHS::reset();31    {32        std::any lhs = LHS(1);33        const std::any rhs = RHS(2);34 35        assert(LHS::count == 1);36        assert(RHS::count == 1);37        assert(RHS::copied == 0);38 39        lhs = rhs;40 41        assert(RHS::copied == 1);42        assert(LHS::count == 0);43        assert(RHS::count == 2);44 45        assertContains<RHS>(lhs, 2);46        assertContains<RHS>(rhs, 2);47    }48    assert(LHS::count == 0);49    assert(RHS::count == 0);50    LHS::reset();51    RHS::reset();52    {53        std::any lhs = LHS(1);54        std::any rhs = RHS(2);55 56        assert(LHS::count == 1);57        assert(RHS::count == 1);58        assert(RHS::moved == 1);59 60        lhs = std::move(rhs);61 62        assert(RHS::moved >= 1);63        assert(RHS::copied == 0);64        assert(LHS::count == 0);65        assert(RHS::count == 1 + rhs.has_value());66        LIBCPP_ASSERT(!rhs.has_value());67 68        assertContains<RHS>(lhs, 2);69        if (rhs.has_value())70            assertContains<RHS>(rhs, 0);71    }72    assert(LHS::count == 0);73    assert(RHS::count == 0);74}75 76template <class RHS>77void test_assign_value_empty() {78    assert(RHS::count == 0);79    RHS::reset();80    {81        std::any lhs;82        RHS rhs(42);83        assert(RHS::count == 1);84        assert(RHS::copied == 0);85 86        lhs = rhs;87 88        assert(RHS::count == 2);89        assert(RHS::copied == 1);90        assert(RHS::moved >= 0);91        assertContains<RHS>(lhs, 42);92    }93    assert(RHS::count == 0);94    RHS::reset();95    {96        std::any lhs;97        RHS rhs(42);98        assert(RHS::count == 1);99        assert(RHS::moved == 0);100 101        lhs = std::move(rhs);102 103        assert(RHS::count == 2);104        assert(RHS::copied == 0);105        assert(RHS::moved >= 1);106        assertContains<RHS>(lhs, 42);107    }108    assert(RHS::count == 0);109    RHS::reset();110}111 112 113template <class Tp, bool Move = false>114void test_assign_throws() {115#if !defined(TEST_HAS_NO_EXCEPTIONS)116    auto try_throw =117    [](std::any& lhs, Tp& rhs) {118        try {119            Move ? lhs = std::move(rhs)120                 : lhs = rhs;121            assert(false);122        } catch (const my_any_exception&) {123            // do nothing124        } catch (...) {125            assert(false);126        }127    };128    // const lvalue to empty129    {130        std::any lhs;131        Tp rhs(1);132        assert(Tp::count == 1);133 134        try_throw(lhs, rhs);135 136        assert(Tp::count == 1);137        assertEmpty<Tp>(lhs);138    }139    {140        std::any lhs = small(2);141        Tp rhs(1);142        assert(small::count == 1);143        assert(Tp::count == 1);144 145        try_throw(lhs, rhs);146 147        assert(small::count == 1);148        assert(Tp::count == 1);149        assertContains<small>(lhs, 2);150    }151    {152        std::any lhs = large(2);153        Tp rhs(1);154        assert(large::count == 1);155        assert(Tp::count == 1);156 157        try_throw(lhs, rhs);158 159        assert(large::count == 1);160        assert(Tp::count == 1);161        assertContains<large>(lhs, 2);162    }163#endif164}165 166 167// Test that any& operator=(ValueType&&) is *never* selected for:168// * std::in_place type.169// * Non-copyable types170void test_sfinae_constraints() {171    { // Only the constructors are required to SFINAE on in_place_t172        using Tag = std::in_place_type_t<int>;173        using RawTag = std::remove_reference_t<Tag>;174        static_assert(std::is_assignable<std::any, RawTag&&>::value, "");175    }176    {177        struct Dummy { Dummy() = delete; };178        using T = std::in_place_type_t<Dummy>;179        static_assert(std::is_assignable<std::any, T>::value, "");180    }181    {182        // Test that the ValueType&& constructor SFINAE's away when the183        // argument is non-copyable184        struct NoCopy {185          NoCopy() = default;186          NoCopy(NoCopy const&) = delete;187          NoCopy(NoCopy&&) = default;188        };189        static_assert(!std::is_assignable<std::any, NoCopy>::value, "");190        static_assert(!std::is_assignable<std::any, NoCopy&>::value, "");191    }192}193 194int main(int, char**) {195    test_assign_value<small1, small2>();196    test_assign_value<large1, large2>();197    test_assign_value<small, large>();198    test_assign_value<large, small>();199    test_assign_value_empty<small>();200    test_assign_value_empty<large>();201    test_assign_throws<small_throws_on_copy>();202    test_assign_throws<large_throws_on_copy>();203    test_assign_throws<throws_on_move, /* Move = */ true>();204    test_sfinae_constraints();205 206  return 0;207}208