131 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// <memory>10 11// unique_ptr12 13// Test swap14 15#include <memory>16#include <cassert>17 18#include "test_macros.h"19#include "deleter_types.h"20 21struct A22{23 int state_;24 static int count;25 TEST_CONSTEXPR_CXX23 A() : state_(0) {26 if (!TEST_IS_CONSTANT_EVALUATED)27 ++count;28 }29 TEST_CONSTEXPR_CXX23 explicit A(int i) : state_(i) {30 if (!TEST_IS_CONSTANT_EVALUATED)31 ++count;32 }33 TEST_CONSTEXPR_CXX23 A(const A& a) : state_(a.state_) {34 if (!TEST_IS_CONSTANT_EVALUATED)35 ++count;36 }37 TEST_CONSTEXPR_CXX23 A& operator=(const A& a) {38 state_ = a.state_;39 return *this;40 }41 TEST_CONSTEXPR_CXX23 ~A() {42 if (!TEST_IS_CONSTANT_EVALUATED)43 --count;44 }45 46 friend TEST_CONSTEXPR_CXX23 bool operator==(const A& x, const A& y) { return x.state_ == y.state_; }47};48 49int A::count = 0;50 51template <class T>52struct NonSwappableDeleter {53 TEST_CONSTEXPR_CXX23 explicit NonSwappableDeleter(int) {}54 TEST_CONSTEXPR_CXX23 NonSwappableDeleter& operator=(NonSwappableDeleter const&) { return *this; }55 TEST_CONSTEXPR_CXX23 void operator()(T*) const {}56 57private:58 NonSwappableDeleter(NonSwappableDeleter const&);59 60};61 62TEST_CONSTEXPR_CXX23 bool test() {63 {64 A* p1 = new A(1);65 std::unique_ptr<A, Deleter<A> > s1(p1, Deleter<A>(1));66 A* p2 = new A(2);67 std::unique_ptr<A, Deleter<A> > s2(p2, Deleter<A>(2));68 assert(s1.get() == p1);69 assert(*s1 == A(1));70 assert(s1.get_deleter().state() == 1);71 assert(s2.get() == p2);72 assert(*s2 == A(2));73 assert(s2.get_deleter().state() == 2);74 swap(s1, s2);75 assert(s1.get() == p2);76 assert(*s1 == A(2));77 assert(s1.get_deleter().state() == 2);78 assert(s2.get() == p1);79 assert(*s2 == A(1));80 assert(s2.get_deleter().state() == 1);81 if (!TEST_IS_CONSTANT_EVALUATED)82 assert(A::count == 2);83 }84 if (!TEST_IS_CONSTANT_EVALUATED)85 assert(A::count == 0);86 {87 A* p1 = new A[3];88 std::unique_ptr<A[], Deleter<A[]> > s1(p1, Deleter<A[]>(1));89 A* p2 = new A[3];90 std::unique_ptr<A[], Deleter<A[]> > s2(p2, Deleter<A[]>(2));91 assert(s1.get() == p1);92 assert(s1.get_deleter().state() == 1);93 assert(s2.get() == p2);94 assert(s2.get_deleter().state() == 2);95 swap(s1, s2);96 assert(s1.get() == p2);97 assert(s1.get_deleter().state() == 2);98 assert(s2.get() == p1);99 assert(s2.get_deleter().state() == 1);100 if (!TEST_IS_CONSTANT_EVALUATED)101 assert(A::count == 6);102 }103 if (!TEST_IS_CONSTANT_EVALUATED)104 assert(A::count == 0);105#if TEST_STD_VER >= 11106 {107 // test that unique_ptr's specialized swap is disabled when the deleter108 // is non-swappable. Instead we should pick up the generic swap(T, T)109 // and perform 3 move constructions.110 typedef NonSwappableDeleter<int> D;111 D d(42);112 int x = 42;113 int y = 43;114 std::unique_ptr<int, D&> p(&x, d);115 std::unique_ptr<int, D&> p2(&y, d);116 std::swap(p, p2);117 }118#endif119 120 return true;121}122 123int main(int, char**) {124 test();125#if TEST_STD_VER >= 23126 static_assert(test());127#endif128 129 return 0;130}131