166 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// <memory>12 13// unique_ptr14 15// Test unique_ptr converting move assignment16 17#include <memory>18#include <utility>19#include <cassert>20 21#include "test_macros.h"22#include "deleter_types.h"23#include "unique_ptr_test_helper.h"24 25template <class APtr, class BPtr>26TEST_CONSTEXPR_CXX23 void testAssign(APtr& aptr, BPtr& bptr) {27 A* p = bptr.get();28 if (!TEST_IS_CONSTANT_EVALUATED)29 assert(A::count == 2);30 aptr = std::move(bptr);31 assert(aptr.get() == p);32 assert(bptr.get() == 0);33 if (!TEST_IS_CONSTANT_EVALUATED) {34 assert(A::count == 1);35 assert(B::count == 1);36 }37}38 39template <class LHS, class RHS>40TEST_CONSTEXPR_CXX23 void checkDeleter(LHS& lhs, RHS& rhs, int LHSState, int RHSState) {41 assert(lhs.get_deleter().state() == LHSState);42 assert(rhs.get_deleter().state() == RHSState);43}44 45template <class T>46struct NCConvertingDeleter {47 TEST_CONSTEXPR_CXX23 NCConvertingDeleter() = default;48 NCConvertingDeleter(NCConvertingDeleter const&) = delete;49 TEST_CONSTEXPR_CXX23 NCConvertingDeleter(NCConvertingDeleter&&) = default;50 51 template <class U>52 TEST_CONSTEXPR_CXX23 NCConvertingDeleter(NCConvertingDeleter<U>&&) {}53 54 TEST_CONSTEXPR_CXX23 void operator()(T*) const {}55};56 57template <class T>58struct NCConvertingDeleter<T[]> {59 TEST_CONSTEXPR_CXX23 NCConvertingDeleter() = default;60 NCConvertingDeleter(NCConvertingDeleter const&) = delete;61 TEST_CONSTEXPR_CXX23 NCConvertingDeleter(NCConvertingDeleter&&) = default;62 63 template <class U>64 TEST_CONSTEXPR_CXX23 NCConvertingDeleter(NCConvertingDeleter<U>&&) {}65 66 TEST_CONSTEXPR_CXX23 void operator()(T*) const {}67};68 69struct NCGenericDeleter {70 TEST_CONSTEXPR_CXX23 NCGenericDeleter() = default;71 NCGenericDeleter(NCGenericDeleter const&) = delete;72 TEST_CONSTEXPR_CXX23 NCGenericDeleter(NCGenericDeleter&&) = default;73 74 TEST_CONSTEXPR_CXX23 void operator()(void*) const {}75};76 77TEST_CONSTEXPR_CXX23 void test_sfinae() {78 using DA = NCConvertingDeleter<A>; // non-copyable deleters79 using DB = NCConvertingDeleter<B>;80 using UA = std::unique_ptr<A>;81 using UB = std::unique_ptr<B>;82 using UAD = std::unique_ptr<A, DA>;83 using UBD = std::unique_ptr<B, DB>;84 { // cannot move from an lvalue85 static_assert(std::is_assignable<UA, UB&&>::value, "");86 static_assert(!std::is_assignable<UA, UB&>::value, "");87 static_assert(!std::is_assignable<UA, const UB&>::value, "");88 }89 { // cannot move if the deleter-types cannot convert90 static_assert(std::is_assignable<UAD, UBD&&>::value, "");91 static_assert(!std::is_assignable<UAD, UB&&>::value, "");92 static_assert(!std::is_assignable<UA, UBD&&>::value, "");93 }94 { // cannot move-convert with reference deleters of different types95 using UA1 = std::unique_ptr<A, DA&>;96 using UB1 = std::unique_ptr<B, DB&>;97 static_assert(!std::is_assignable<UA1, UB1&&>::value, "");98 }99 { // cannot move-convert with reference deleters of different types100 using UA1 = std::unique_ptr<A, const DA&>;101 using UB1 = std::unique_ptr<B, const DB&>;102 static_assert(!std::is_assignable<UA1, UB1&&>::value, "");103 }104 { // cannot move-convert from unique_ptr<Array[]>105 using UA1 = std::unique_ptr<A>;106 using UA2 = std::unique_ptr<A[]>;107 using UB1 = std::unique_ptr<B[]>;108 static_assert(!std::is_assignable<UA1, UA2&&>::value, "");109 static_assert(!std::is_assignable<UA1, UB1&&>::value, "");110 }111 { // cannot move-convert from unique_ptr<Array[]>112 using UA1 = std::unique_ptr<A, NCGenericDeleter>;113 using UA2 = std::unique_ptr<A[], NCGenericDeleter>;114 using UB1 = std::unique_ptr<B[], NCGenericDeleter>;115 static_assert(!std::is_assignable<UA1, UA2&&>::value, "");116 static_assert(!std::is_assignable<UA1, UB1&&>::value, "");117 }118}119 120TEST_CONSTEXPR_CXX23 bool test() {121 test_sfinae();122 {123 std::unique_ptr<B> bptr(new B);124 std::unique_ptr<A> aptr(new A);125 testAssign(aptr, bptr);126 }127 if (!TEST_IS_CONSTANT_EVALUATED) {128 assert(A::count == 0);129 assert(B::count == 0);130 }131 {132 Deleter<B> del(42);133 std::unique_ptr<B, Deleter<B> > bptr(new B, std::move(del));134 std::unique_ptr<A, Deleter<A> > aptr(new A);135 testAssign(aptr, bptr);136 checkDeleter(aptr, bptr, 42, 0);137 }138 if (!TEST_IS_CONSTANT_EVALUATED) {139 assert(A::count == 0);140 assert(B::count == 0);141 }142 {143 CDeleter<A> adel(6);144 CDeleter<B> bdel(42);145 std::unique_ptr<B, CDeleter<B>&> bptr(new B, bdel);146 std::unique_ptr<A, CDeleter<A>&> aptr(new A, adel);147 testAssign(aptr, bptr);148 checkDeleter(aptr, bptr, 42, 42);149 }150 if (!TEST_IS_CONSTANT_EVALUATED) {151 assert(A::count == 0);152 assert(B::count == 0);153 }154 155 return true;156}157 158int main(int, char**) {159 test();160#if TEST_STD_VER >= 23161 static_assert(test());162#endif163 164 return 0;165}166