brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.1 KiB · 8e5d9c3 Raw
144 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++0310 11// <utility>12 13// template <class T1, class T2> struct pair14 15// pair& operator=(pair&& p);16 17#include <utility>18#include <memory>19#include <cassert>20 21#include "test_macros.h"22#include "archetypes.h"23 24struct CountAssign {25  int copied = 0;26  int moved = 0;27  TEST_CONSTEXPR_CXX20 CountAssign() = default;28  TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) {29    ++copied;30    return *this;31  }32  TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) {33    ++moved;34    return *this;35  }36};37 38struct NotAssignable {39  NotAssignable& operator=(NotAssignable const&) = delete;40  NotAssignable& operator=(NotAssignable&&) = delete;41};42 43struct MoveAssignable {44  MoveAssignable& operator=(MoveAssignable const&) = delete;45  MoveAssignable& operator=(MoveAssignable&&) = default;46};47 48struct CopyAssignable {49  CopyAssignable& operator=(CopyAssignable const&) = default;50  CopyAssignable& operator=(CopyAssignable&&) = delete;51};52 53TEST_CONSTEXPR_CXX20 bool test() {54  {55    typedef std::pair<ConstexprTestTypes::MoveOnly, int> P;56    P p1(3, 4);57    P p2;58    p2 = std::move(p1);59    assert(p2.first.value == 3);60    assert(p2.second == 4);61  }62  {63    using P = std::pair<int&, int&&>;64    int x = 42;65    int y = 101;66    int x2 = -1;67    int y2 = 300;68    P p1(x, std::move(y));69    P p2(x2, std::move(y2));70    p1 = std::move(p2);71    assert(p1.first == x2);72    assert(p1.second == y2);73  }74  {75    using P = std::pair<int, ConstexprTestTypes::DefaultOnly>;76    static_assert(!std::is_move_assignable<P>::value, "");77  }78  {79    // The move decays to the copy constructor80    using P = std::pair<CountAssign, ConstexprTestTypes::CopyOnly>;81    static_assert(std::is_move_assignable<P>::value, "");82    P p;83    P p2;84    p = std::move(p2);85    assert(p.first.moved == 0);86    assert(p.first.copied == 1);87    assert(p2.first.moved == 0);88    assert(p2.first.copied == 0);89  }90  {91    using P = std::pair<CountAssign, ConstexprTestTypes::MoveOnly>;92    static_assert(std::is_move_assignable<P>::value, "");93    P p;94    P p2;95    p = std::move(p2);96    assert(p.first.moved == 1);97    assert(p.first.copied == 0);98    assert(p2.first.moved == 0);99    assert(p2.first.copied == 0);100  }101  {102    using P1 = std::pair<int, NotAssignable>;103    using P2 = std::pair<NotAssignable, int>;104    using P3 = std::pair<NotAssignable, NotAssignable>;105    static_assert(!std::is_move_assignable<P1>::value, "");106    static_assert(!std::is_move_assignable<P2>::value, "");107    static_assert(!std::is_move_assignable<P3>::value, "");108  }109  {110    // We assign through the reference and don't move out of the incoming ref,111    // so this doesn't work (but would if the type were CopyAssignable).112    using P1 = std::pair<MoveAssignable&, int>;113    static_assert(!std::is_move_assignable<P1>::value, "");114 115    // ... works if it's CopyAssignable116    using P2 = std::pair<CopyAssignable&, int>;117    static_assert(std::is_move_assignable<P2>::value, "");118 119    // For rvalue-references, we can move-assign if the type is MoveAssignable120    // or CopyAssignable (since in the worst case the move will decay into a copy).121    using P3 = std::pair<MoveAssignable&&, int>;122    using P4 = std::pair<CopyAssignable&&, int>;123    static_assert(std::is_move_assignable<P3>::value, "");124    static_assert(std::is_move_assignable<P4>::value, "");125 126    // In all cases, we can't move-assign if the types are not assignable,127    // since we assign through the reference.128    using P5 = std::pair<NotAssignable&, int>;129    using P6 = std::pair<NotAssignable&&, int>;130    static_assert(!std::is_move_assignable<P5>::value, "");131    static_assert(!std::is_move_assignable<P6>::value, "");132  }133  return true;134}135 136int main(int, char**) {137  test();138#if TEST_STD_VER >= 20139  static_assert(test());140#endif141 142  return 0;143}144