Add support for "fancy" pointers to shared_ptr. Fixes PR20616
Summary: This patch add support for "fancy pointers/allocators" as well as fixing support for shared_pointer and "minimal" allocators. Fancy pointers are class types that meet the NullablePointer requirements. In our case they are created by fancy allocators. `support/min_allocator.h` is an archetype for these types. There are three types of changes made in this patch: 1. `_Alloc::template rebind<T>::other` -> `__allocator_traits_rebind<_Alloc, T>::type`. This change was made because allocators don't need a rebind template. `__allocator_traits_rebind` is used instead of `allocator_traits::rebind` because use of `allocator_traits::rebind` requires a workaround for when template aliases are unavailable. 2. `a.deallocate(this, 1)` -> `a.deallocate(pointer_traits<self>::pointer_to(*this), 1)`. This change change is made because fancy pointers aren't always constructible from raw pointers. 3. `p.get()` -> `addressof(*p.get())`. Fancy pointers aren't actually a pointer. When we need a "real" pointer we take the address of dereferencing the fancy pointer. This should give us the actual raw pointer. Test Plan: Tests were added using `support/min_allocator.h` to each affected shared_ptr overload and creation function. These tests can only be executed in C++11 or greater since min_allocator is only available then. A extra test was added for the non-variadic versions of allocate_shared. Reviewers: danalbert, mclow.lists Reviewed By: mclow.lists Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D4859 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@220469 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9b82e151fe
commit
4e7d53664d
@ -3677,9 +3677,13 @@ template <class _Tp, class _Dp, class _Alloc>
|
|||||||
void
|
void
|
||||||
__shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT
|
__shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT
|
||||||
{
|
{
|
||||||
typename _Alloc::template rebind<__shared_ptr_pointer>::other __a(__data_.second());
|
typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_pointer>::type _A;
|
||||||
|
typedef allocator_traits<_A> _ATraits;
|
||||||
|
typedef pointer_traits<typename _ATraits::pointer> _PTraits;
|
||||||
|
|
||||||
|
_A __a(__data_.second());
|
||||||
__data_.second().~_Alloc();
|
__data_.second().~_Alloc();
|
||||||
__a.deallocate(this, 1);
|
__a.deallocate(_PTraits::pointer_to(*this), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Tp, class _Alloc>
|
template <class _Tp, class _Alloc>
|
||||||
@ -3742,9 +3746,12 @@ template <class _Tp, class _Alloc>
|
|||||||
void
|
void
|
||||||
__shared_ptr_emplace<_Tp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT
|
__shared_ptr_emplace<_Tp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT
|
||||||
{
|
{
|
||||||
typename _Alloc::template rebind<__shared_ptr_emplace>::other __a(__data_.first());
|
typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type _A;
|
||||||
|
typedef allocator_traits<_A> _ATraits;
|
||||||
|
typedef pointer_traits<typename _ATraits::pointer> _PTraits;
|
||||||
|
_A __a(__data_.first());
|
||||||
__data_.first().~_Alloc();
|
__data_.first().~_Alloc();
|
||||||
__a.deallocate(this, 1);
|
__a.deallocate(_PTraits::pointer_to(*this), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class _Tp> class _LIBCPP_TYPE_VIS_ONLY enable_shared_from_this;
|
template<class _Tp> class _LIBCPP_TYPE_VIS_ONLY enable_shared_from_this;
|
||||||
@ -4090,12 +4097,13 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
|
|||||||
{
|
{
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk;
|
typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk;
|
||||||
typedef typename _Alloc::template rebind<_CntrlBlk>::other _A2;
|
typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
|
||||||
typedef __allocator_destructor<_A2> _D2;
|
typedef __allocator_destructor<_A2> _D2;
|
||||||
_A2 __a2(__a);
|
_A2 __a2(__a);
|
||||||
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
|
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
|
||||||
::new(__hold2.get()) _CntrlBlk(__p, __d, __a);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
|
||||||
__cntrl_ = __hold2.release();
|
_CntrlBlk(__p, __d, __a);
|
||||||
|
__cntrl_ = _VSTD::addressof(*__hold2.release());
|
||||||
__enable_weak_this(__p);
|
__enable_weak_this(__p);
|
||||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
}
|
}
|
||||||
@ -4117,12 +4125,13 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a)
|
|||||||
{
|
{
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk;
|
typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk;
|
||||||
typedef typename _Alloc::template rebind<_CntrlBlk>::other _A2;
|
typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
|
||||||
typedef __allocator_destructor<_A2> _D2;
|
typedef __allocator_destructor<_A2> _D2;
|
||||||
_A2 __a2(__a);
|
_A2 __a2(__a);
|
||||||
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
|
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
|
||||||
::new(__hold2.get()) _CntrlBlk(__p, __d, __a);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
|
||||||
__cntrl_ = __hold2.release();
|
_CntrlBlk(__p, __d, __a);
|
||||||
|
__cntrl_ = _VSTD::addressof(*__hold2.release());
|
||||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
@ -4282,14 +4291,15 @@ shared_ptr<_Tp>
|
|||||||
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _Args&& ...__args)
|
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _Args&& ...__args)
|
||||||
{
|
{
|
||||||
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
||||||
typedef typename _Alloc::template rebind<_CntrlBlk>::other _A2;
|
typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
|
||||||
typedef __allocator_destructor<_A2> _D2;
|
typedef __allocator_destructor<_A2> _D2;
|
||||||
_A2 __a2(__a);
|
_A2 __a2(__a);
|
||||||
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
|
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
|
||||||
::new(__hold2.get()) _CntrlBlk(__a, _VSTD::forward<_Args>(__args)...);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
|
||||||
|
_CntrlBlk(__a, _VSTD::forward<_Args>(__args)...);
|
||||||
shared_ptr<_Tp> __r;
|
shared_ptr<_Tp> __r;
|
||||||
__r.__ptr_ = __hold2.get()->get();
|
__r.__ptr_ = __hold2.get()->get();
|
||||||
__r.__cntrl_ = __hold2.release();
|
__r.__cntrl_ = _VSTD::addressof(*__hold2.release());
|
||||||
__r.__enable_weak_this(__r.__ptr_);
|
__r.__enable_weak_this(__r.__ptr_);
|
||||||
return __r;
|
return __r;
|
||||||
}
|
}
|
||||||
@ -4373,14 +4383,15 @@ shared_ptr<_Tp>
|
|||||||
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a)
|
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a)
|
||||||
{
|
{
|
||||||
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
||||||
typedef typename _Alloc::template rebind<_CntrlBlk>::other _Alloc2;
|
typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
|
||||||
typedef __allocator_destructor<_Alloc2> _D2;
|
typedef __allocator_destructor<_Alloc2> _D2;
|
||||||
_Alloc2 __alloc2(__a);
|
_Alloc2 __alloc2(__a);
|
||||||
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
|
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
|
||||||
::new(__hold2.get()) _CntrlBlk(__a);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
|
||||||
|
_CntrlBlk(__a);
|
||||||
shared_ptr<_Tp> __r;
|
shared_ptr<_Tp> __r;
|
||||||
__r.__ptr_ = __hold2.get()->get();
|
__r.__ptr_ = __hold2.get()->get();
|
||||||
__r.__cntrl_ = __hold2.release();
|
__r.__cntrl_ = _VSTD::addressof(*__hold2.release());
|
||||||
__r.__enable_weak_this(__r.__ptr_);
|
__r.__enable_weak_this(__r.__ptr_);
|
||||||
return __r;
|
return __r;
|
||||||
}
|
}
|
||||||
@ -4391,14 +4402,15 @@ shared_ptr<_Tp>
|
|||||||
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0)
|
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0)
|
||||||
{
|
{
|
||||||
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
||||||
typedef typename _Alloc::template rebind<_CntrlBlk>::other _Alloc2;
|
typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
|
||||||
typedef __allocator_destructor<_Alloc2> _D2;
|
typedef __allocator_destructor<_Alloc2> _D2;
|
||||||
_Alloc2 __alloc2(__a);
|
_Alloc2 __alloc2(__a);
|
||||||
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
|
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
|
||||||
::new(__hold2.get()) _CntrlBlk(__a, __a0);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
|
||||||
|
_CntrlBlk(__a, __a0);
|
||||||
shared_ptr<_Tp> __r;
|
shared_ptr<_Tp> __r;
|
||||||
__r.__ptr_ = __hold2.get()->get();
|
__r.__ptr_ = __hold2.get()->get();
|
||||||
__r.__cntrl_ = __hold2.release();
|
__r.__cntrl_ = _VSTD::addressof(*__hold2.release());
|
||||||
__r.__enable_weak_this(__r.__ptr_);
|
__r.__enable_weak_this(__r.__ptr_);
|
||||||
return __r;
|
return __r;
|
||||||
}
|
}
|
||||||
@ -4409,14 +4421,15 @@ shared_ptr<_Tp>
|
|||||||
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0, _A1& __a1)
|
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0, _A1& __a1)
|
||||||
{
|
{
|
||||||
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
||||||
typedef typename _Alloc::template rebind<_CntrlBlk>::other _Alloc2;
|
typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
|
||||||
typedef __allocator_destructor<_Alloc2> _D2;
|
typedef __allocator_destructor<_Alloc2> _D2;
|
||||||
_Alloc2 __alloc2(__a);
|
_Alloc2 __alloc2(__a);
|
||||||
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
|
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
|
||||||
::new(__hold2.get()) _CntrlBlk(__a, __a0, __a1);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
|
||||||
|
_CntrlBlk(__a, __a0, __a1);
|
||||||
shared_ptr<_Tp> __r;
|
shared_ptr<_Tp> __r;
|
||||||
__r.__ptr_ = __hold2.get()->get();
|
__r.__ptr_ = __hold2.get()->get();
|
||||||
__r.__cntrl_ = __hold2.release();
|
__r.__cntrl_ = _VSTD::addressof(*__hold2.release());
|
||||||
__r.__enable_weak_this(__r.__ptr_);
|
__r.__enable_weak_this(__r.__ptr_);
|
||||||
return __r;
|
return __r;
|
||||||
}
|
}
|
||||||
@ -4427,14 +4440,15 @@ shared_ptr<_Tp>
|
|||||||
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0, _A1& __a1, _A2& __a2)
|
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0, _A1& __a1, _A2& __a2)
|
||||||
{
|
{
|
||||||
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
|
||||||
typedef typename _Alloc::template rebind<_CntrlBlk>::other _Alloc2;
|
typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
|
||||||
typedef __allocator_destructor<_Alloc2> _D2;
|
typedef __allocator_destructor<_Alloc2> _D2;
|
||||||
_Alloc2 __alloc2(__a);
|
_Alloc2 __alloc2(__a);
|
||||||
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
|
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
|
||||||
::new(__hold2.get()) _CntrlBlk(__a, __a0, __a1, __a2);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
|
||||||
|
_CntrlBlk(__a, __a0, __a1, __a2);
|
||||||
shared_ptr<_Tp> __r;
|
shared_ptr<_Tp> __r;
|
||||||
__r.__ptr_ = __hold2.get()->get();
|
__r.__ptr_ = __hold2.get()->get();
|
||||||
__r.__cntrl_ = __hold2.release();
|
__r.__cntrl_ = _VSTD::addressof(*__hold2.release());
|
||||||
__r.__enable_weak_this(__r.__ptr_);
|
__r.__enable_weak_this(__r.__ptr_);
|
||||||
return __r;
|
return __r;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../test_deleter.h"
|
#include "../test_deleter.h"
|
||||||
#include "test_allocator.h"
|
#include "test_allocator.h"
|
||||||
|
#include "min_allocator.h"
|
||||||
|
|
||||||
struct A
|
struct A
|
||||||
{
|
{
|
||||||
@ -47,4 +48,38 @@ int main()
|
|||||||
assert(test_deleter<A>::dealloc_count == 1);
|
assert(test_deleter<A>::dealloc_count == 1);
|
||||||
assert(test_allocator<A>::count == 0);
|
assert(test_allocator<A>::count == 0);
|
||||||
assert(test_allocator<A>::alloc_count == 0);
|
assert(test_allocator<A>::alloc_count == 0);
|
||||||
|
test_deleter<A>::dealloc_count = 0;
|
||||||
|
// Test an allocator with a minimal interface
|
||||||
|
{
|
||||||
|
std::shared_ptr<A> p(nullptr, test_deleter<A>(1), bare_allocator<void>());
|
||||||
|
assert(A::count == 0);
|
||||||
|
assert(p.use_count() == 1);
|
||||||
|
assert(p.get() == 0);
|
||||||
|
test_deleter<A>* d = std::get_deleter<test_deleter<A> >(p);
|
||||||
|
assert(test_deleter<A>::count ==1);
|
||||||
|
assert(test_deleter<A>::dealloc_count == 0);
|
||||||
|
assert(d);
|
||||||
|
assert(d->state() == 1);
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
assert(test_deleter<A>::count == 0);
|
||||||
|
assert(test_deleter<A>::dealloc_count == 1);
|
||||||
|
test_deleter<A>::dealloc_count = 0;
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
// Test an allocator that returns class-type pointers
|
||||||
|
{
|
||||||
|
std::shared_ptr<A> p(nullptr, test_deleter<A>(1), min_allocator<void>());
|
||||||
|
assert(A::count == 0);
|
||||||
|
assert(p.use_count() == 1);
|
||||||
|
assert(p.get() == 0);
|
||||||
|
test_deleter<A>* d = std::get_deleter<test_deleter<A> >(p);
|
||||||
|
assert(test_deleter<A>::count ==1);
|
||||||
|
assert(test_deleter<A>::dealloc_count == 0);
|
||||||
|
assert(d);
|
||||||
|
assert(d->state() == 1);
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
assert(test_deleter<A>::count == 0);
|
||||||
|
assert(test_deleter<A>::dealloc_count == 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../test_deleter.h"
|
#include "../test_deleter.h"
|
||||||
#include "test_allocator.h"
|
#include "test_allocator.h"
|
||||||
|
#include "min_allocator.h"
|
||||||
|
|
||||||
struct A
|
struct A
|
||||||
{
|
{
|
||||||
@ -27,6 +28,7 @@ struct A
|
|||||||
|
|
||||||
int A::count = 0;
|
int A::count = 0;
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -48,4 +50,40 @@ int main()
|
|||||||
assert(test_deleter<A>::dealloc_count == 1);
|
assert(test_deleter<A>::dealloc_count == 1);
|
||||||
assert(test_allocator<A>::count == 0);
|
assert(test_allocator<A>::count == 0);
|
||||||
assert(test_allocator<A>::alloc_count == 0);
|
assert(test_allocator<A>::alloc_count == 0);
|
||||||
|
test_deleter<A>::dealloc_count = 0;
|
||||||
|
// Test an allocator with a minimal interface
|
||||||
|
{
|
||||||
|
A* ptr = new A;
|
||||||
|
std::shared_ptr<A> p(ptr, test_deleter<A>(3), bare_allocator<void>());
|
||||||
|
assert(A::count == 1);
|
||||||
|
assert(p.use_count() == 1);
|
||||||
|
assert(p.get() == ptr);
|
||||||
|
test_deleter<A>* d = std::get_deleter<test_deleter<A> >(p);
|
||||||
|
assert(test_deleter<A>::count == 1);
|
||||||
|
assert(test_deleter<A>::dealloc_count == 0);
|
||||||
|
assert(d);
|
||||||
|
assert(d->state() == 3);
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
assert(test_deleter<A>::count == 0);
|
||||||
|
assert(test_deleter<A>::dealloc_count == 1);
|
||||||
|
test_deleter<A>::dealloc_count = 0;
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
// Test an allocator that returns class-type pointers
|
||||||
|
{
|
||||||
|
A* ptr = new A;
|
||||||
|
std::shared_ptr<A> p(ptr, test_deleter<A>(3), min_allocator<void>());
|
||||||
|
assert(A::count == 1);
|
||||||
|
assert(p.use_count() == 1);
|
||||||
|
assert(p.get() == ptr);
|
||||||
|
test_deleter<A>* d = std::get_deleter<test_deleter<A> >(p);
|
||||||
|
assert(test_deleter<A>::count == 1);
|
||||||
|
assert(test_deleter<A>::dealloc_count == 0);
|
||||||
|
assert(d);
|
||||||
|
assert(d->state() == 3);
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
assert(test_deleter<A>::count == 0);
|
||||||
|
assert(test_deleter<A>::dealloc_count == 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "test_allocator.h"
|
#include "test_allocator.h"
|
||||||
|
#include "min_allocator.h"
|
||||||
|
|
||||||
int new_count = 0;
|
int new_count = 0;
|
||||||
|
|
||||||
@ -54,4 +55,24 @@ int main()
|
|||||||
}
|
}
|
||||||
assert(A::count == 0);
|
assert(A::count == 0);
|
||||||
assert(test_allocator<A>::alloc_count == 0);
|
assert(test_allocator<A>::alloc_count == 0);
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
{
|
||||||
|
int i = 67;
|
||||||
|
char c = 'e';
|
||||||
|
std::shared_ptr<A> p = std::allocate_shared<A>(min_allocator<void>(), i, c);
|
||||||
|
assert(A::count == 1);
|
||||||
|
assert(p->get_int() == 67);
|
||||||
|
assert(p->get_char() == 'e');
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
{
|
||||||
|
int i = 68;
|
||||||
|
char c = 'f';
|
||||||
|
std::shared_ptr<A> p = std::allocate_shared<A>(bare_allocator<void>(), i, c);
|
||||||
|
assert(A::count == 1);
|
||||||
|
assert(p->get_int() == 68);
|
||||||
|
assert(p->get_char() == 'f');
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,118 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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>
|
||||||
|
|
||||||
|
// shared_ptr
|
||||||
|
|
||||||
|
// template<class T, class A, class... Args>
|
||||||
|
// shared_ptr<T> allocate_shared(const A& a, Args&&... args);
|
||||||
|
|
||||||
|
#define _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
#include <memory>
|
||||||
|
#include <new>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include "test_allocator.h"
|
||||||
|
#include "min_allocator.h"
|
||||||
|
|
||||||
|
struct Zero
|
||||||
|
{
|
||||||
|
static int count;
|
||||||
|
Zero() {++count;}
|
||||||
|
Zero(Zero const &) {++count;}
|
||||||
|
~Zero() {--count;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int Zero::count = 0;
|
||||||
|
|
||||||
|
struct One
|
||||||
|
{
|
||||||
|
static int count;
|
||||||
|
int value;
|
||||||
|
explicit One(int v) : value(v) {++count;}
|
||||||
|
One(One const & o) : value(o.value) {++count;}
|
||||||
|
~One() {--count;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int One::count = 0;
|
||||||
|
|
||||||
|
|
||||||
|
struct Two
|
||||||
|
{
|
||||||
|
static int count;
|
||||||
|
int value;
|
||||||
|
Two(int v, int) : value(v) {++count;}
|
||||||
|
Two(Two const & o) : value(o.value) {++count;}
|
||||||
|
~Two() {--count;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int Two::count = 0;
|
||||||
|
|
||||||
|
struct Three
|
||||||
|
{
|
||||||
|
static int count;
|
||||||
|
int value;
|
||||||
|
Three(int v, int, int) : value(v) {++count;}
|
||||||
|
Three(Three const & o) : value(o.value) {++count;}
|
||||||
|
~Three() {--count;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int Three::count = 0;
|
||||||
|
|
||||||
|
template <class Alloc>
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
int const bad = -1;
|
||||||
|
{
|
||||||
|
std::shared_ptr<Zero> p = std::allocate_shared<Zero>(Alloc());
|
||||||
|
assert(Zero::count == 1);
|
||||||
|
}
|
||||||
|
assert(Zero::count == 0);
|
||||||
|
{
|
||||||
|
int const i = 42;
|
||||||
|
std::shared_ptr<One> p = std::allocate_shared<One>(Alloc(), i);
|
||||||
|
assert(One::count == 1);
|
||||||
|
assert(p->value == i);
|
||||||
|
}
|
||||||
|
assert(One::count == 0);
|
||||||
|
{
|
||||||
|
int const i = 42;
|
||||||
|
std::shared_ptr<Two> p = std::allocate_shared<Two>(Alloc(), i, bad);
|
||||||
|
assert(Two::count == 1);
|
||||||
|
assert(p->value == i);
|
||||||
|
}
|
||||||
|
assert(Two::count == 0);
|
||||||
|
{
|
||||||
|
int const i = 42;
|
||||||
|
std::shared_ptr<Three> p = std::allocate_shared<Three>(Alloc(), i, bad, bad);
|
||||||
|
assert(Three::count == 1);
|
||||||
|
assert(p->value == i);
|
||||||
|
}
|
||||||
|
assert(Three::count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
int i = 67;
|
||||||
|
int const bad = -1;
|
||||||
|
std::shared_ptr<Two> p = std::allocate_shared<Two>(test_allocator<Two>(54), i, bad);
|
||||||
|
assert(test_allocator<Two>::alloc_count == 1);
|
||||||
|
assert(Two::count == 1);
|
||||||
|
assert(p->value == 67);
|
||||||
|
}
|
||||||
|
assert(Two::count == 0);
|
||||||
|
assert(test_allocator<Two>::alloc_count == 0);
|
||||||
|
|
||||||
|
test<bare_allocator<void> >();
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
test<min_allocator<void> >();
|
||||||
|
#endif
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user