blob: 4c5cc843a138c963486d66c33fb0b008636bcca3 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <memory>
// unique_ptr
// Test unique_ptr move ctor
#include <memory>
#include <utility>
#include <cassert>
#include "../../deleter.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<T, D> 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<T, D>
// from a temporary. 'source' should return the unique_ptr by value and
// 'sink' should accept the unique_ptr by value. (C-1,2,4)
struct A
{
static int count;
A() {++count;}
A(const A&) {++count;}
virtual ~A() {--count;}
};
int A::count = 0;
template <class Expect>
void sinkFunction(Expect)
{
}
typedef std::unique_ptr<A> APtrSource1;
typedef std::unique_ptr<A, Deleter<A> > APtrSource2;
typedef std::unique_ptr<A, NCDeleter<A>& > APtrSource3;
APtrSource1 source1() {
return APtrSource1 (new A);
}
void sink1(APtrSource1 p) {
assert(p.get() != nullptr);
}
APtrSource2 source2() {
return APtrSource2(new A, Deleter<A>(5));
}
void sink2(APtrSource2 p) {
assert(p.get() != nullptr);
assert(p.get_deleter().state() == 5);
}
APtrSource3 source3() {
static NCDeleter<A> d(5);
return APtrSource3(new A, d);
}
void sink3(APtrSource3 p) {
assert(p.get() != nullptr);
assert(p.get_deleter().state() == 5);
assert(&p.get_deleter() == &source3().get_deleter());
}
int main()
{
{
typedef std::unique_ptr<A> APtr;
APtr s(new A);
A* p = s.get();
APtr s2 = std::move(s);
assert(s2.get() == p);
assert(s.get() == 0);
assert(A::count == 1);
}
assert(A::count == 0);
{
typedef Deleter<A> MoveDel;
typedef std::unique_ptr<A, MoveDel> APtr;
MoveDel d(5);
APtr s(new A, 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 == 1);
assert(s2.get_deleter().state() == 5);
assert(s.get_deleter().state() == 0);
}
assert(A::count == 0);
{
typedef NCDeleter<A> NonCopyDel;
typedef std::unique_ptr<A, NonCopyDel&> APtr;
NonCopyDel d;
APtr s(new A, d);
A* p = s.get();
APtr s2 = std::move(s);
assert(s2.get() == p);
assert(s.get() == 0);
assert(A::count == 1);
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);
}