xref: /llvm-project/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.special/swap.pass.cpp (revision 30dadaa2eb499395f5bef44b9e1a18db6360ad1f)
12561885fSEric Fiselier //===----------------------------------------------------------------------===//
22561885fSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62561885fSEric Fiselier //
72561885fSEric Fiselier //===----------------------------------------------------------------------===//
82561885fSEric Fiselier 
92561885fSEric Fiselier // <memory>
102561885fSEric Fiselier 
112561885fSEric Fiselier // unique_ptr
122561885fSEric Fiselier 
132561885fSEric Fiselier // Test swap
142561885fSEric Fiselier 
152561885fSEric Fiselier #include <memory>
162561885fSEric Fiselier #include <cassert>
172561885fSEric Fiselier 
182561885fSEric Fiselier #include "test_macros.h"
192561885fSEric Fiselier #include "deleter_types.h"
202561885fSEric Fiselier 
212561885fSEric Fiselier struct A
222561885fSEric Fiselier {
232561885fSEric Fiselier     int state_;
242561885fSEric Fiselier     static int count;
AA25*30dadaa2SIgor Zhukov     TEST_CONSTEXPR_CXX23 A() : state_(0) {
26*30dadaa2SIgor Zhukov       if (!TEST_IS_CONSTANT_EVALUATED)
27*30dadaa2SIgor Zhukov         ++count;
28*30dadaa2SIgor Zhukov     }
AA29*30dadaa2SIgor Zhukov     TEST_CONSTEXPR_CXX23 explicit A(int i) : state_(i) {
30*30dadaa2SIgor Zhukov       if (!TEST_IS_CONSTANT_EVALUATED)
31*30dadaa2SIgor Zhukov         ++count;
32*30dadaa2SIgor Zhukov     }
AA33*30dadaa2SIgor Zhukov     TEST_CONSTEXPR_CXX23 A(const A& a) : state_(a.state_) {
34*30dadaa2SIgor Zhukov       if (!TEST_IS_CONSTANT_EVALUATED)
35*30dadaa2SIgor Zhukov         ++count;
36*30dadaa2SIgor Zhukov     }
operator =A37*30dadaa2SIgor Zhukov     TEST_CONSTEXPR_CXX23 A& operator=(const A& a) {
38*30dadaa2SIgor Zhukov       state_ = a.state_;
39*30dadaa2SIgor Zhukov       return *this;
40*30dadaa2SIgor Zhukov     }
~AA41*30dadaa2SIgor Zhukov     TEST_CONSTEXPR_CXX23 ~A() {
42*30dadaa2SIgor Zhukov       if (!TEST_IS_CONSTANT_EVALUATED)
43*30dadaa2SIgor Zhukov         --count;
44*30dadaa2SIgor Zhukov     }
452561885fSEric Fiselier 
operator ==(const A & x,const A & y)46*30dadaa2SIgor Zhukov     friend TEST_CONSTEXPR_CXX23 bool operator==(const A& x, const A& y) { return x.state_ == y.state_; }
472561885fSEric Fiselier };
482561885fSEric Fiselier 
492561885fSEric Fiselier int A::count = 0;
502561885fSEric Fiselier 
512561885fSEric Fiselier template <class T>
522561885fSEric Fiselier struct NonSwappableDeleter {
NonSwappableDeleterNonSwappableDeleter53*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 explicit NonSwappableDeleter(int) {}
operator =NonSwappableDeleter54*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 NonSwappableDeleter& operator=(NonSwappableDeleter const&) { return *this; }
operator ()NonSwappableDeleter55*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 void operator()(T*) const {}
56*30dadaa2SIgor Zhukov 
572561885fSEric Fiselier private:
582561885fSEric Fiselier   NonSwappableDeleter(NonSwappableDeleter const&);
592561885fSEric Fiselier 
602561885fSEric Fiselier };
612561885fSEric Fiselier 
test()62*30dadaa2SIgor Zhukov TEST_CONSTEXPR_CXX23 bool test() {
632561885fSEric Fiselier   {
642561885fSEric Fiselier     A* p1 = new A(1);
652561885fSEric Fiselier     std::unique_ptr<A, Deleter<A> > s1(p1, Deleter<A>(1));
662561885fSEric Fiselier     A* p2 = new A(2);
672561885fSEric Fiselier     std::unique_ptr<A, Deleter<A> > s2(p2, Deleter<A>(2));
682561885fSEric Fiselier     assert(s1.get() == p1);
692561885fSEric Fiselier     assert(*s1 == A(1));
702561885fSEric Fiselier     assert(s1.get_deleter().state() == 1);
712561885fSEric Fiselier     assert(s2.get() == p2);
722561885fSEric Fiselier     assert(*s2 == A(2));
732561885fSEric Fiselier     assert(s2.get_deleter().state() == 2);
742561885fSEric Fiselier     swap(s1, s2);
752561885fSEric Fiselier     assert(s1.get() == p2);
762561885fSEric Fiselier     assert(*s1 == A(2));
772561885fSEric Fiselier     assert(s1.get_deleter().state() == 2);
782561885fSEric Fiselier     assert(s2.get() == p1);
792561885fSEric Fiselier     assert(*s2 == A(1));
802561885fSEric Fiselier     assert(s2.get_deleter().state() == 1);
81*30dadaa2SIgor Zhukov     if (!TEST_IS_CONSTANT_EVALUATED)
822561885fSEric Fiselier       assert(A::count == 2);
832561885fSEric Fiselier   }
84*30dadaa2SIgor Zhukov   if (!TEST_IS_CONSTANT_EVALUATED)
852561885fSEric Fiselier     assert(A::count == 0);
862561885fSEric Fiselier   {
872561885fSEric Fiselier     A* p1 = new A[3];
882561885fSEric Fiselier     std::unique_ptr<A[], Deleter<A[]> > s1(p1, Deleter<A[]>(1));
892561885fSEric Fiselier     A* p2 = new A[3];
902561885fSEric Fiselier     std::unique_ptr<A[], Deleter<A[]> > s2(p2, Deleter<A[]>(2));
912561885fSEric Fiselier     assert(s1.get() == p1);
922561885fSEric Fiselier     assert(s1.get_deleter().state() == 1);
932561885fSEric Fiselier     assert(s2.get() == p2);
942561885fSEric Fiselier     assert(s2.get_deleter().state() == 2);
952561885fSEric Fiselier     swap(s1, s2);
962561885fSEric Fiselier     assert(s1.get() == p2);
972561885fSEric Fiselier     assert(s1.get_deleter().state() == 2);
982561885fSEric Fiselier     assert(s2.get() == p1);
992561885fSEric Fiselier     assert(s2.get_deleter().state() == 1);
100*30dadaa2SIgor Zhukov     if (!TEST_IS_CONSTANT_EVALUATED)
1012561885fSEric Fiselier       assert(A::count == 6);
1022561885fSEric Fiselier   }
103*30dadaa2SIgor Zhukov   if (!TEST_IS_CONSTANT_EVALUATED)
1042561885fSEric Fiselier     assert(A::count == 0);
1052561885fSEric Fiselier #if TEST_STD_VER >= 11
1062561885fSEric Fiselier     {
1072561885fSEric Fiselier         // test that unique_ptr's specialized swap is disabled when the deleter
1082561885fSEric Fiselier         // is non-swappable. Instead we should pick up the generic swap(T, T)
1092561885fSEric Fiselier         // and perform 3 move constructions.
1102561885fSEric Fiselier         typedef NonSwappableDeleter<int> D;
1112561885fSEric Fiselier         D  d(42);
1122561885fSEric Fiselier         int x = 42;
1132561885fSEric Fiselier         int y = 43;
1142561885fSEric Fiselier         std::unique_ptr<int, D&> p(&x, d);
1152561885fSEric Fiselier         std::unique_ptr<int, D&> p2(&y, d);
1162561885fSEric Fiselier         std::swap(p, p2);
1172561885fSEric Fiselier     }
1182561885fSEric Fiselier #endif
1192df59c50SJF Bastien 
120*30dadaa2SIgor Zhukov     return true;
121*30dadaa2SIgor Zhukov }
122*30dadaa2SIgor Zhukov 
main(int,char **)123*30dadaa2SIgor Zhukov int main(int, char**) {
124*30dadaa2SIgor Zhukov   test();
125*30dadaa2SIgor Zhukov #if TEST_STD_VER >= 23
126*30dadaa2SIgor Zhukov   static_assert(test());
127*30dadaa2SIgor Zhukov #endif
128*30dadaa2SIgor Zhukov 
1292df59c50SJF Bastien   return 0;
1302561885fSEric Fiselier }
131