130 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 "unique_ptr_test_helper.h"23 24template <class APtr, class BPtr>25void testAssign(APtr& aptr, BPtr& bptr) {26 A* p = bptr.get();27 assert(A::count == 2);28 aptr = std::move(bptr);29 assert(aptr.get() == p);30 assert(bptr.get() == 0);31 assert(A::count == 1);32 assert(B::count == 1);33}34 35template <class LHS, class RHS>36void checkDeleter(LHS& lhs, RHS& rhs, int LHSState, int RHSState) {37 assert(lhs.get_deleter().state() == LHSState);38 assert(rhs.get_deleter().state() == RHSState);39}40 41template <class T>42struct NCConvertingDeleter {43 NCConvertingDeleter() = default;44 NCConvertingDeleter(NCConvertingDeleter const&) = delete;45 NCConvertingDeleter(NCConvertingDeleter&&) = default;46 47 template <class U>48 NCConvertingDeleter(NCConvertingDeleter<U>&&) {}49 50 void operator()(T*) const {}51};52 53template <class T>54struct NCConvertingDeleter<T[]> {55 NCConvertingDeleter() = default;56 NCConvertingDeleter(NCConvertingDeleter const&) = delete;57 NCConvertingDeleter(NCConvertingDeleter&&) = default;58 59 template <class U>60 NCConvertingDeleter(NCConvertingDeleter<U>&&) {}61 62 void operator()(T*) const {}63};64 65struct GenericDeleter {66 void operator()(void*) const;67};68 69struct NCGenericDeleter {70 NCGenericDeleter() = default;71 NCGenericDeleter(NCGenericDeleter const&) = delete;72 NCGenericDeleter(NCGenericDeleter&&) = default;73 74 void operator()(void*) const {}75};76 77void test_sfinae() {78 using DA = NCConvertingDeleter<A[]>; // non-copyable deleters79 using DAC = NCConvertingDeleter<const A[]>; // non-copyable deleters80 81 using UA = std::unique_ptr<A[]>;82 using UAC = std::unique_ptr<const A[]>;83 using UAD = std::unique_ptr<A[], DA>;84 using UACD = std::unique_ptr<const A[], DAC>;85 86 { // cannot move from an lvalue87 static_assert(std::is_assignable<UAC, UA&&>::value, "");88 static_assert(!std::is_assignable<UAC, UA&>::value, "");89 static_assert(!std::is_assignable<UAC, const UA&>::value, "");90 }91 { // cannot move if the deleter-types cannot convert92 static_assert(std::is_assignable<UACD, UAD&&>::value, "");93 static_assert(!std::is_assignable<UACD, UAC&&>::value, "");94 static_assert(!std::is_assignable<UAC, UACD&&>::value, "");95 }96 { // cannot move-convert with reference deleters of different types97 using UA1 = std::unique_ptr<A[], DA&>;98 using UA2 = std::unique_ptr<A[], DAC&>;99 static_assert(!std::is_assignable<UA1, UA2&&>::value, "");100 }101 { // cannot move-convert with reference deleters of different types102 using UA1 = std::unique_ptr<A[], const DA&>;103 using UA2 = std::unique_ptr<A[], const DAC&>;104 static_assert(!std::is_assignable<UA1, UA2&&>::value, "");105 }106 { // cannot move-convert with reference deleters with different qualifiers107 using UA1 = std::unique_ptr<A[], DA&>;108 using UA2 = std::unique_ptr<A[], const DA&>;109 static_assert(!std::is_assignable<UA1, UA2&&>::value, "");110 static_assert(!std::is_assignable<UA2, UA1&&>::value, "");111 }112 { // cannot move-convert from unique_ptr<Single>113 using UA1 = std::unique_ptr<A[]>;114 using UA2 = std::unique_ptr<A>;115 static_assert(!std::is_assignable<UA1, UA2&&>::value, "");116 }117 { // cannot move-convert from unique_ptr<Array[]>118 using UA1 = std::unique_ptr<A[], NCGenericDeleter>;119 using UA2 = std::unique_ptr<A, NCGenericDeleter>;120 static_assert(!std::is_assignable<UA1, UA2&&>::value, "");121 }122}123 124int main(int, char**) {125 test_sfinae();126 // FIXME: add tests127 128 return 0;129}130