201 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 unique_ptr move ctor14 15#include <memory>16#include <utility>17#include <cassert>18 19#include "test_macros.h"20#include "unique_ptr_test_helper.h"21 22//=============================================================================23// TESTING unique_ptr(unique_ptr&&)24//25// Concerns26// 1 The moved from pointer is empty and the new pointer stores the old value.27// 2 The only requirement on the deleter is that it is MoveConstructible28// or a reference.29// 3 The constructor works for explicitly moved values (i.e. std::move(x))30// 4 The constructor works for true temporaries (e.g. a return value)31//32// Plan33// 1 Explicitly construct unique_ptr<T, D> for various deleter types 'D'.34// check that the value and deleter have been properly moved. (C-1,2,3)35//36// 2 Use the expression 'sink(source())' to move construct a unique_ptr<T, D>37// from a temporary. 'source' should return the unique_ptr by value and38// 'sink' should accept the unique_ptr by value. (C-1,2,4)39 40template <class VT>41TEST_CONSTEXPR_CXX23 std::unique_ptr<VT> source1() {42 return std::unique_ptr<VT>(newValue<VT>(1));43}44 45template <class VT>46TEST_CONSTEXPR_CXX23 std::unique_ptr<VT, Deleter<VT> > source2() {47 return std::unique_ptr<VT, Deleter<VT> >(newValue<VT>(1), Deleter<VT>(5));48}49 50template <class VT>51std::unique_ptr<VT, NCDeleter<VT>&> source3() {52 static NCDeleter<VT> d(5);53 return std::unique_ptr<VT, NCDeleter<VT>&>(newValue<VT>(1), d);54}55 56template <class VT>57TEST_CONSTEXPR_CXX23 void sink1(std::unique_ptr<VT> p) {58 assert(p.get() != nullptr);59}60 61template <class VT>62TEST_CONSTEXPR_CXX23 void sink2(std::unique_ptr<VT, Deleter<VT> > p) {63 assert(p.get() != nullptr);64 assert(p.get_deleter().state() == 5);65}66 67template <class VT>68void sink3(std::unique_ptr<VT, NCDeleter<VT>&> p) {69 assert(p.get() != nullptr);70 assert(p.get_deleter().state() == 5);71 assert(&p.get_deleter() == &source3<VT>().get_deleter());72}73 74template <class ValueT>75TEST_CONSTEXPR_CXX23 void test_sfinae() {76 typedef std::unique_ptr<ValueT> U;77 { // Ensure unique_ptr is non-copyable78 static_assert((!std::is_constructible<U, U const&>::value), "");79 static_assert((!std::is_constructible<U, U&>::value), "");80 }81}82 83template <bool IsArray>84TEST_CONSTEXPR_CXX23 void test_basic() {85 typedef typename std::conditional<!IsArray, A, A[]>::type VT;86 const int expect_alive = IsArray ? 5 : 1;87 {88 typedef std::unique_ptr<VT> APtr;89 APtr s(newValue<VT>(expect_alive));90 A* p = s.get();91 APtr s2 = std::move(s);92 assert(s2.get() == p);93 assert(s.get() == 0);94 if (!TEST_IS_CONSTANT_EVALUATED)95 assert(A::count == expect_alive);96 }97 if (!TEST_IS_CONSTANT_EVALUATED)98 assert(A::count == 0);99 {100 typedef Deleter<VT> MoveDel;101 typedef std::unique_ptr<VT, MoveDel> APtr;102 MoveDel d(5);103 APtr s(newValue<VT>(expect_alive), std::move(d));104 assert(d.state() == 0);105 assert(s.get_deleter().state() == 5);106 A* p = s.get();107 APtr s2 = std::move(s);108 assert(s2.get() == p);109 assert(s.get() == 0);110 if (!TEST_IS_CONSTANT_EVALUATED)111 assert(A::count == expect_alive);112 assert(s2.get_deleter().state() == 5);113 assert(s.get_deleter().state() == 0);114 }115 if (!TEST_IS_CONSTANT_EVALUATED)116 assert(A::count == 0);117 {118 typedef NCDeleter<VT> NonCopyDel;119 typedef std::unique_ptr<VT, NonCopyDel&> APtr;120 121 NonCopyDel d;122 APtr s(newValue<VT>(expect_alive), d);123 A* p = s.get();124 APtr s2 = std::move(s);125 assert(s2.get() == p);126 assert(s.get() == 0);127 if (!TEST_IS_CONSTANT_EVALUATED)128 assert(A::count == expect_alive);129 d.set_state(6);130 assert(s2.get_deleter().state() == d.state());131 assert(s.get_deleter().state() == d.state());132 }133 if (!TEST_IS_CONSTANT_EVALUATED)134 assert(A::count == 0);135 {136 sink1<VT>(source1<VT>());137 if (!TEST_IS_CONSTANT_EVALUATED)138 assert(A::count == 0);139 sink2<VT>(source2<VT>());140 if (!TEST_IS_CONSTANT_EVALUATED)141 assert(A::count == 0);142 }143 if (!TEST_IS_CONSTANT_EVALUATED)144 assert(A::count == 0);145}146 147template <class VT>148TEST_CONSTEXPR_CXX23 void test_noexcept() {149#if TEST_STD_VER >= 11150 {151 typedef std::unique_ptr<VT> U;152 static_assert(std::is_nothrow_move_constructible<U>::value, "");153 }154 {155 typedef std::unique_ptr<VT, Deleter<VT> > U;156 static_assert(std::is_nothrow_move_constructible<U>::value, "");157 }158 {159 typedef std::unique_ptr<VT, NCDeleter<VT> &> U;160 static_assert(std::is_nothrow_move_constructible<U>::value, "");161 }162 {163 typedef std::unique_ptr<VT, const NCConstDeleter<VT> &> U;164 static_assert(std::is_nothrow_move_constructible<U>::value, "");165 }166#endif167}168 169TEST_CONSTEXPR_CXX23 bool test() {170 {171 test_basic</*IsArray*/ false>();172 test_sfinae<int>();173 test_noexcept<int>();174 }175 {176 test_basic</*IsArray*/ true>();177 test_sfinae<int[]>();178 test_noexcept<int[]>();179 }180 181 return true;182}183 184template <bool IsArray>185void test_sink3() {186 typedef typename std::conditional<!IsArray, A, A[]>::type VT;187 sink3<VT>(source3<VT>());188 assert(A::count == 0);189}190 191int main(int, char**) {192 test_sink3</*IsArray*/ false>();193 test_sink3</*IsArray*/ true>();194 test();195#if TEST_STD_VER >= 23196 static_assert(test());197#endif198 199 return 0;200}201