//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // unique_ptr //============================================================================= // TESTING std::unique_ptr::unique_ptr(pointer) // // Concerns: // 1 The pointer constructor works for any default constructible deleter types. // 2 The pointer constructor accepts pointers to derived types. // 2 The stored type 'T' is allowed to be incomplete. // // Plan // 1 Construct unique_ptr's with a pointer to 'T' and various deleter // types (C-1) // 2 Construct unique_ptr's with a pointer to 'D' and various deleter // types where 'D' is derived from 'T'. (C-1,2) // 3 Construct a unique_ptr with a pointer to 'T' and various deleter // types where 'T' is an incomplete type (C-1,3) // Test unique_ptr(pointer) ctor #include #include #include "test_macros.h" #include "unique_ptr_test_helper.h" // unique_ptr(pointer) ctor should only require default Deleter ctor template TEST_CONSTEXPR_CXX23 void test_pointer() { typedef typename std::conditional::type ValueT; const int expect_alive = IsArray ? 5 : 1; #if TEST_STD_VER >= 11 { using U1 = std::unique_ptr; using U2 = std::unique_ptr >; // Test for noexcept static_assert(std::is_nothrow_constructible::value, ""); static_assert(std::is_nothrow_constructible::value, ""); // Test for explicit static_assert(!std::is_convertible::value, ""); static_assert(!std::is_convertible::value, ""); } #endif { A* p = newValue(expect_alive); if (!TEST_IS_CONSTANT_EVALUATED) assert(A::count == expect_alive); std::unique_ptr s(p); assert(s.get() == p); } if (!TEST_IS_CONSTANT_EVALUATED) assert(A::count == 0); { A* p = newValue(expect_alive); if (!TEST_IS_CONSTANT_EVALUATED) assert(A::count == expect_alive); std::unique_ptr > s(p); assert(s.get() == p); assert(s.get_deleter().state() == 0); } if (!TEST_IS_CONSTANT_EVALUATED) assert(A::count == 0); { A* p = newValue(expect_alive); if (!TEST_IS_CONSTANT_EVALUATED) assert(A::count == expect_alive); std::unique_ptr > s(p); assert(s.get() == p); assert(s.get_deleter().state() == 0); } if (!TEST_IS_CONSTANT_EVALUATED) assert(A::count == 0); } TEST_CONSTEXPR_CXX23 void test_derived() { { B* p = new B; if (!TEST_IS_CONSTANT_EVALUATED) { assert(A::count == 1); assert(B::count == 1); } std::unique_ptr s(p); assert(s.get() == p); } if (!TEST_IS_CONSTANT_EVALUATED) { assert(A::count == 0); assert(B::count == 0); } { B* p = new B; if (!TEST_IS_CONSTANT_EVALUATED) { assert(A::count == 1); assert(B::count == 1); } std::unique_ptr > s(p); assert(s.get() == p); assert(s.get_deleter().state() == 0); } if (!TEST_IS_CONSTANT_EVALUATED) { assert(A::count == 0); assert(B::count == 0); } } #if TEST_STD_VER >= 11 struct NonDefaultDeleter { NonDefaultDeleter() = delete; void operator()(void*) const {} }; struct GenericDeleter { void operator()(void*) const; }; #endif template void TEST_CONSTEXPR_CXX23 test_sfinae() { #if TEST_STD_VER >= 11 { // the constructor does not participate in overload resolution when // the deleter is a pointer type using U = std::unique_ptr; static_assert(!std::is_constructible::value, ""); } { // the constructor does not participate in overload resolution when // the deleter is not default constructible using Del = CDeleter; using U1 = std::unique_ptr; using U2 = std::unique_ptr; using U3 = std::unique_ptr; static_assert(!std::is_constructible::value, ""); static_assert(!std::is_constructible::value, ""); static_assert(!std::is_constructible::value, ""); } #endif } static TEST_CONSTEXPR_CXX23 void test_sfinae_runtime() { #if TEST_STD_VER >= 11 { // the constructor does not participate in overload resolution when // a base <-> derived conversion would occur. using UA = std::unique_ptr; using UAD = std::unique_ptr; using UAC = std::unique_ptr; using UB = std::unique_ptr; using UBD = std::unique_ptr; using UBC = std::unique_ptr; static_assert(!std::is_constructible::value, ""); static_assert(!std::is_constructible::value, ""); static_assert(!std::is_constructible::value, ""); static_assert(!std::is_constructible::value, ""); static_assert(!std::is_constructible::value, ""); static_assert(!std::is_constructible::value, ""); } #endif } DEFINE_AND_RUN_IS_INCOMPLETE_TEST({ { doIncompleteTypeTest(1, getNewIncomplete()); } checkNumIncompleteTypeAlive(0); { doIncompleteTypeTest >( 1, getNewIncomplete()); } checkNumIncompleteTypeAlive(0); }) TEST_CONSTEXPR_CXX23 bool test() { { test_pointer(); test_derived(); test_sfinae(); } { test_pointer(); test_sfinae(); test_sfinae_runtime(); } return true; } int main(int, char**) { test(); #if TEST_STD_VER >= 23 static_assert(test()); #endif return 0; }