More unique_ptr test cleanup. Fixes in <memory> to come later.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@245512 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
de56f74611
commit
672575dadc
@ -112,7 +112,6 @@ public:
|
|||||||
|
|
||||||
~Deleter() {assert(state_ >= 0); state_ = -1;}
|
~Deleter() {assert(state_ >= 0); state_ = -1;}
|
||||||
|
|
||||||
private:
|
|
||||||
template <class U>
|
template <class U>
|
||||||
Deleter(Deleter<U> d,
|
Deleter(Deleter<U> d,
|
||||||
typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
|
typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
|
||||||
|
@ -32,5 +32,5 @@ int main()
|
|||||||
{
|
{
|
||||||
std::unique_ptr<A[], Deleter> s;
|
std::unique_ptr<A[], Deleter> s;
|
||||||
std::unique_ptr<A, Deleter> s2;
|
std::unique_ptr<A, Deleter> s2;
|
||||||
s2 = std::move(s);
|
s2 = std::move(s); // expected-error {{no viable overloaded '='}}
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,21 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// libc++ cannot safely provide the auto_ptr constructor without rvalue
|
||||||
|
// references.
|
||||||
|
// XFAIL: c++98, c++03
|
||||||
|
|
||||||
// <memory>
|
// <memory>
|
||||||
|
|
||||||
// unique_ptr
|
// unique_ptr
|
||||||
|
|
||||||
// Test unique_ptr(pointer) ctor
|
// template <class U> unique_ptr(auto_ptr<U>&&) noexcept
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
// template <class U> explicit unique_ptr(auto_ptr<U>&);
|
#include "test_macros.h"
|
||||||
|
|
||||||
struct A
|
struct A
|
||||||
{
|
{
|
||||||
@ -65,4 +69,12 @@ int main()
|
|||||||
}
|
}
|
||||||
assert(A::count == 0);
|
assert(A::count == 0);
|
||||||
assert(B::count == 0);
|
assert(B::count == 0);
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{
|
||||||
|
static_assert(std::is_nothrow_constructible<
|
||||||
|
std::unique_ptr<A>,
|
||||||
|
std::auto_ptr<B>&&
|
||||||
|
>::value, "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
// XFAIL: c++98, c++03
|
// XFAIL: c++98, c++03
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -50,126 +51,121 @@ struct B
|
|||||||
|
|
||||||
int B::count = 0;
|
int B::count = 0;
|
||||||
|
|
||||||
template <class OrigPtr, class NewPtr>
|
|
||||||
void checkDeleter(OrigPtr& O, NewPtr& N, int OrigState, int NewState) {
|
template <class LHS, class RHS>
|
||||||
typedef typename NewPtr::deleter_type NewDel;
|
void checkReferenceDeleter(LHS& lhs, RHS& rhs) {
|
||||||
if (std::is_reference<NewDel>::value) {
|
typedef typename LHS::deleter_type NewDel;
|
||||||
O.get_deleter().set_state(42);
|
static_assert(std::is_reference<NewDel>::value, "");
|
||||||
assert(O.get_deleter().state() == 42);
|
rhs.get_deleter().set_state(42);
|
||||||
assert(N.get_deleter().state() == 42);
|
assert(rhs.get_deleter().state() == 42);
|
||||||
O.get_deleter().set_state(99);
|
assert(lhs.get_deleter().state() == 42);
|
||||||
assert(O.get_deleter().state() == 99);
|
lhs.get_deleter().set_state(99);
|
||||||
assert(N.get_deleter().state() == 99);
|
assert(lhs.get_deleter().state() == 99);
|
||||||
} else {
|
assert(rhs.get_deleter().state() == 99);
|
||||||
// TODO(EricWF) Enable this?
|
|
||||||
// assert(OrigState != NewState);
|
|
||||||
assert(O.get_deleter().state() == OrigState);
|
|
||||||
assert(N.get_deleter().state() == NewState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class APtr, class BPtr>
|
template <class LHS, class RHS>
|
||||||
void testMoveConvertExplicit()
|
void checkDeleter(LHS& lhs, RHS& rhs, int LHSVal, int RHSVal) {
|
||||||
{
|
assert(lhs.get_deleter().state() == LHSVal);
|
||||||
{ // Test explicit constructor
|
assert(rhs.get_deleter().state() == RHSVal);
|
||||||
BPtr s(new B);
|
}
|
||||||
A* p = s.get();
|
|
||||||
APtr s2(std::move(s));
|
template <class LHS, class RHS>
|
||||||
assert(s2.get() == p);
|
void checkCtor(LHS& lhs, RHS& rhs, A* RHSVal) {
|
||||||
assert(s.get() == 0);
|
assert(lhs.get() == RHSVal);
|
||||||
assert(A::count == 1);
|
assert(rhs.get() == nullptr);
|
||||||
assert(B::count == 1);
|
assert(A::count == 1);
|
||||||
}
|
assert(B::count == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkNoneAlive() {
|
||||||
assert(A::count == 0);
|
assert(A::count == 0);
|
||||||
assert(B::count == 0);
|
assert(B::count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class APtr, class BPtr>
|
|
||||||
void testMoveConvertImplicit() {
|
|
||||||
|
|
||||||
{ // Test implicit constructor
|
|
||||||
BPtr s(new B);
|
|
||||||
A* p = s.get();
|
|
||||||
APtr s2 = std::move(s);
|
|
||||||
assert(s2.get() == p);
|
|
||||||
assert(s.get() == 0);
|
|
||||||
assert(A::count == 1);
|
|
||||||
assert(B::count == 1);
|
|
||||||
}
|
|
||||||
assert(A::count == 0);
|
|
||||||
assert(B::count == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class APtr, class BPtr, class Deleter>
|
|
||||||
#if TEST_STD_VER >= 11
|
|
||||||
void testMoveConvertExplicit(Deleter&& del) {
|
|
||||||
#else
|
|
||||||
void testMoveConvert(Deleter& del) {
|
|
||||||
#endif
|
|
||||||
int old_val = del.state();
|
|
||||||
{ // Test Explicit constructor
|
|
||||||
BPtr s(new B, std::forward<Deleter>(del));
|
|
||||||
A* p = s.get();
|
|
||||||
APtr s2(std::move(s));
|
|
||||||
assert(s2.get() == p);
|
|
||||||
assert(s.get() == 0);
|
|
||||||
checkDeleter(s, s2, del.state(), old_val);
|
|
||||||
assert(A::count == 1);
|
|
||||||
assert(B::count == 1);
|
|
||||||
}
|
|
||||||
assert(A::count == 0);
|
|
||||||
assert(B::count == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class APtr, class BPtr, class Deleter>
|
|
||||||
#if TEST_STD_VER >= 11
|
|
||||||
void testMoveConvertImplicit(Deleter&& del) {
|
|
||||||
#else
|
|
||||||
void testMoveConvertImplicit(Deleter& del) {
|
|
||||||
#endif
|
|
||||||
int old_val = del.state();
|
|
||||||
{ // Test Implicit constructor
|
|
||||||
BPtr s(new B, std::forward<Deleter>(del));
|
|
||||||
A* p = s.get();
|
|
||||||
APtr s2 = std::move(s);
|
|
||||||
assert(s2.get() == p);
|
|
||||||
assert(s.get() == 0);
|
|
||||||
checkDeleter(s, s2, del.state(), old_val);
|
|
||||||
assert(A::count == 1);
|
|
||||||
assert(B::count == 1);
|
|
||||||
}
|
|
||||||
assert(A::count == 0);
|
|
||||||
assert(B::count == 0);
|
|
||||||
}
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
typedef std::unique_ptr<A> APtr;
|
typedef std::unique_ptr<A> APtr;
|
||||||
typedef std::unique_ptr<B> BPtr;
|
typedef std::unique_ptr<B> BPtr;
|
||||||
testMoveConvertExplicit<APtr, BPtr>();
|
{ // explicit
|
||||||
testMoveConvertImplicit<APtr, BPtr>();
|
BPtr b(new B);
|
||||||
|
A* p = b.get();
|
||||||
|
APtr a(std::move(b));
|
||||||
|
checkCtor(a, b, p);
|
||||||
|
}
|
||||||
|
checkNoneAlive();
|
||||||
|
{ // implicit
|
||||||
|
BPtr b(new B);
|
||||||
|
A* p = b.get();
|
||||||
|
APtr a = std::move(b);
|
||||||
|
checkCtor(a, b, p);
|
||||||
|
}
|
||||||
|
checkNoneAlive();
|
||||||
}
|
}
|
||||||
{
|
{ // test with moveable deleters
|
||||||
typedef std::unique_ptr<A, Deleter<A> > APtr;
|
typedef std::unique_ptr<A, Deleter<A> > APtr;
|
||||||
typedef std::unique_ptr<B, Deleter<B> > BPtr;
|
typedef std::unique_ptr<B, Deleter<B> > BPtr;
|
||||||
Deleter<B> del(5);
|
{
|
||||||
testMoveConvertExplicit<APtr, BPtr>(std::move(del));
|
Deleter<B> del(5);
|
||||||
del.set_state(5);
|
BPtr b(new B, std::move(del));
|
||||||
testMoveConvertImplicit<APtr, BPtr>(std::move(del));
|
A* p = b.get();
|
||||||
|
APtr a(std::move(b));
|
||||||
|
checkCtor(a, b, p);
|
||||||
|
checkDeleter(a, b, 5, 0);
|
||||||
|
}
|
||||||
|
checkNoneAlive();
|
||||||
|
{
|
||||||
|
Deleter<B> del(5);
|
||||||
|
BPtr b(new B, std::move(del));
|
||||||
|
A* p = b.get();
|
||||||
|
APtr a = std::move(b);
|
||||||
|
checkCtor(a, b, p);
|
||||||
|
checkDeleter(a, b, 5, 0);
|
||||||
|
}
|
||||||
|
checkNoneAlive();
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{ // test with reference deleters
|
||||||
typedef std::unique_ptr<A, NCDeleter<A>& > APtr;
|
typedef std::unique_ptr<A, NCDeleter<A>& > APtr;
|
||||||
typedef std::unique_ptr<B, NCDeleter<A>& > BPtr;
|
typedef std::unique_ptr<B, NCDeleter<A>& > BPtr;
|
||||||
NCDeleter<A> del(5);
|
NCDeleter<A> del(5);
|
||||||
testMoveConvertExplicit<APtr, BPtr>(del);
|
{
|
||||||
testMoveConvertImplicit<APtr, BPtr>(del);
|
BPtr b(new B, del);
|
||||||
|
A* p = b.get();
|
||||||
|
APtr a(std::move(b));
|
||||||
|
checkCtor(a, b, p);
|
||||||
|
checkReferenceDeleter(a, b);
|
||||||
|
}
|
||||||
|
checkNoneAlive();
|
||||||
|
{
|
||||||
|
BPtr b(new B, del);
|
||||||
|
A* p = b.get();
|
||||||
|
APtr a = std::move(b);
|
||||||
|
checkCtor(a, b, p);
|
||||||
|
checkReferenceDeleter(a, b);
|
||||||
|
}
|
||||||
|
checkNoneAlive();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
typedef std::unique_ptr<A, CDeleter<A> > APtr;
|
typedef std::unique_ptr<A, CDeleter<A> > APtr;
|
||||||
typedef std::unique_ptr<B, CDeleter<B>& > BPtr;
|
typedef std::unique_ptr<B, CDeleter<B>& > BPtr;
|
||||||
CDeleter<B> del(5);
|
CDeleter<B> del(5);
|
||||||
testMoveConvertImplicit<APtr, BPtr>(del);
|
{
|
||||||
testMoveConvertExplicit<APtr, BPtr>(del);
|
BPtr b(new B, del);
|
||||||
|
A* p = b.get();
|
||||||
|
APtr a(std::move(b));
|
||||||
|
checkCtor(a, b, p);
|
||||||
|
checkDeleter(a, b, 5, 5);
|
||||||
|
}
|
||||||
|
checkNoneAlive();
|
||||||
|
{
|
||||||
|
BPtr b(new B, del);
|
||||||
|
A* p = b.get();
|
||||||
|
APtr a = std::move(b);
|
||||||
|
checkCtor(a, b, p);
|
||||||
|
checkDeleter(a, b, 5, 5);
|
||||||
|
}
|
||||||
|
checkNoneAlive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,49 +7,24 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Without rvalue references it is impossible to detect when a rvalue deleter
|
||||||
|
// is given.
|
||||||
|
// XFAIL: c++98, c++03
|
||||||
|
|
||||||
// <memory>
|
// <memory>
|
||||||
|
|
||||||
// unique_ptr
|
// unique_ptr
|
||||||
|
|
||||||
// Test unique_ptr(pointer) ctor
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
// unique_ptr<T, const D&>(pointer, D()) should not compile
|
// unique_ptr<T, const D&>(pointer, D()) should not compile
|
||||||
|
|
||||||
struct A
|
#include <memory>
|
||||||
{
|
|
||||||
static int count;
|
|
||||||
A() {++count;}
|
|
||||||
A(const A&) {++count;}
|
|
||||||
~A() {--count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
int A::count = 0;
|
struct Deleter {
|
||||||
|
void operator()(int* p) const {delete p;}
|
||||||
class Deleter
|
|
||||||
{
|
|
||||||
int state_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Deleter() : state_(5) {}
|
|
||||||
|
|
||||||
int state() const {return state_;}
|
|
||||||
void set_state(int s) {state_ = s;}
|
|
||||||
|
|
||||||
void operator()(A* p) const {delete p;}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
// expected-error@memory:* {{static_assert failed "rvalue deleter bound to reference"}}
|
||||||
A* p = new A;
|
std::unique_ptr<int, const Deleter&> s((int*)nullptr, Deleter()); // expected-note {{requested here}}
|
||||||
assert(A::count == 1);
|
|
||||||
std::unique_ptr<A, const Deleter&> s(p, Deleter());
|
|
||||||
assert(s.get() == p);
|
|
||||||
assert(s.get_deleter().state() == 5);
|
|
||||||
}
|
|
||||||
assert(A::count == 0);
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user