//===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // unique_ptr // Test unique_ptr move ctor #include #include #include #include "test_macros.h" #include "unique_ptr_test_helper.h" //============================================================================= // TESTING unique_ptr(unique_ptr&&) // // Concerns // 1 The moved from pointer is empty and the new pointer stores the old value. // 2 The only requirement on the deleter is that it is MoveConstructible // or a reference. // 3 The constructor works for explicitly moved values (ie std::move(x)) // 4 The constructor works for true temporaries (ie a return value) // // Plan // 1 Explicitly construct unique_ptr for various deleter types 'D'. // check that the value and deleter have been properly moved. (C-1,2,3) // // 2 Use the expression 'sink(source())' to move construct a unique_ptr // from a temporary. 'source' should return the unique_ptr by value and // 'sink' should accept the unique_ptr by value. (C-1,2,4) template std::unique_ptr source1() { return std::unique_ptr(newValue(1)); } template std::unique_ptr > source2() { return std::unique_ptr >(newValue(1), Deleter(5)); } template std::unique_ptr&> source3() { static NCDeleter d(5); return std::unique_ptr&>(newValue(1), d); } template void sink1(std::unique_ptr p) { assert(p.get() != nullptr); } template void sink2(std::unique_ptr > p) { assert(p.get() != nullptr); assert(p.get_deleter().state() == 5); } template void sink3(std::unique_ptr&> p) { assert(p.get() != nullptr); assert(p.get_deleter().state() == 5); assert(&p.get_deleter() == &source3().get_deleter()); } template void test_sfinae() { typedef std::unique_ptr U; { // Ensure unique_ptr is non-copyable static_assert((!std::is_constructible::value), ""); static_assert((!std::is_constructible::value), ""); } } template void test_basic() { typedef typename std::conditional::type VT; const int expect_alive = IsArray ? 5 : 1; { typedef std::unique_ptr APtr; APtr s(newValue(expect_alive)); A* p = s.get(); APtr s2 = std::move(s); assert(s2.get() == p); assert(s.get() == 0); assert(A::count == expect_alive); } assert(A::count == 0); { typedef Deleter MoveDel; typedef std::unique_ptr APtr; MoveDel d(5); APtr s(newValue(expect_alive), std::move(d)); assert(d.state() == 0); assert(s.get_deleter().state() == 5); A* p = s.get(); APtr s2 = std::move(s); assert(s2.get() == p); assert(s.get() == 0); assert(A::count == expect_alive); assert(s2.get_deleter().state() == 5); assert(s.get_deleter().state() == 0); } assert(A::count == 0); { typedef NCDeleter NonCopyDel; typedef std::unique_ptr APtr; NonCopyDel d; APtr s(newValue(expect_alive), d); A* p = s.get(); APtr s2 = std::move(s); assert(s2.get() == p); assert(s.get() == 0); assert(A::count == expect_alive); d.set_state(6); assert(s2.get_deleter().state() == d.state()); assert(s.get_deleter().state() == d.state()); } assert(A::count == 0); { sink1(source1()); assert(A::count == 0); sink2(source2()); assert(A::count == 0); sink3(source3()); assert(A::count == 0); } assert(A::count == 0); } template void test_noexcept() { #if TEST_STD_VER >= 11 { typedef std::unique_ptr U; static_assert(std::is_nothrow_move_constructible::value, ""); } { typedef std::unique_ptr > U; static_assert(std::is_nothrow_move_constructible::value, ""); } { typedef std::unique_ptr &> U; static_assert(std::is_nothrow_move_constructible::value, ""); } { typedef std::unique_ptr &> U; static_assert(std::is_nothrow_move_constructible::value, ""); } #endif } int main() { { test_basic(); test_sfinae(); test_noexcept(); } { test_basic(); test_sfinae(); test_noexcept(); } }