Overhaul unique_ptr - Implement LWG 2801, 2905, 2520.
This patch overhauls both specializations of unique_ptr while implementing the following LWG issues: * LWG 2801 - This issue constrains unique_ptr's constructors when the deleter type is not default constructible. Additionally it adds SFINAE conditions to unique_ptr<T[]>::unique_ptr(Up). * LWG 2905 - This issue reworks the unique_ptr(pointer, /* see below */ deleter) constructors so that they correctly SFINAE when the deleter argument cannot be used to construct the stored deleter. * LWG 2520 - This issue fixes initializing unique_ptr<T[]> from nullptr. Libc++ had previously implemented this issue, but the suggested resolution still broke initialization from NULL. This patch re-works the unique_ptr<T[]>(Up, deleter) overloads so that they accept NULL as well as nullptr. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@300406 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
681
include/memory
681
include/memory
@@ -2313,371 +2313,557 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_CXX03_LANG
|
||||||
|
template <class _Deleter>
|
||||||
|
struct __unique_ptr_deleter_sfinae {
|
||||||
|
static_assert(!is_reference<_Deleter>::value, "incorrect specialization");
|
||||||
|
typedef const _Deleter& __lval_ref_type;
|
||||||
|
typedef _Deleter&& __good_rval_ref_type;
|
||||||
|
typedef true_type __enable_rval_overload;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class _Deleter>
|
||||||
|
struct __unique_ptr_deleter_sfinae<_Deleter const&> {
|
||||||
|
typedef const _Deleter& __lval_ref_type;
|
||||||
|
typedef const _Deleter&& __bad_rval_ref_type;
|
||||||
|
typedef false_type __enable_rval_overload;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class _Deleter>
|
||||||
|
struct __unique_ptr_deleter_sfinae<_Deleter&> {
|
||||||
|
typedef _Deleter& __lval_ref_type;
|
||||||
|
typedef _Deleter&& __bad_rval_ref_type;
|
||||||
|
typedef false_type __enable_rval_overload;
|
||||||
|
};
|
||||||
|
#endif // !defined(_LIBCPP_CXX03_LANG)
|
||||||
|
|
||||||
template <class _Tp, class _Dp = default_delete<_Tp> >
|
template <class _Tp, class _Dp = default_delete<_Tp> >
|
||||||
class _LIBCPP_TEMPLATE_VIS unique_ptr
|
class _LIBCPP_TEMPLATE_VIS unique_ptr {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef _Tp element_type;
|
typedef _Tp element_type;
|
||||||
typedef _Dp deleter_type;
|
typedef _Dp deleter_type;
|
||||||
typedef typename __pointer_type<_Tp, deleter_type>::type pointer;
|
typedef typename __pointer_type<_Tp, deleter_type>::type pointer;
|
||||||
|
|
||||||
|
static_assert(!is_rvalue_reference<deleter_type>::value,
|
||||||
|
"the specified deleter type cannot be an rvalue reference");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
__compressed_pair<pointer, deleter_type> __ptr_;
|
__compressed_pair<pointer, deleter_type> __ptr_;
|
||||||
|
|
||||||
#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
unique_ptr(unique_ptr&);
|
|
||||||
template <class _Up, class _Ep>
|
|
||||||
unique_ptr(unique_ptr<_Up, _Ep>&);
|
|
||||||
unique_ptr& operator=(unique_ptr&);
|
|
||||||
template <class _Up, class _Ep>
|
|
||||||
unique_ptr& operator=(unique_ptr<_Up, _Ep>&);
|
|
||||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
|
|
||||||
struct __nat { int __for_bool_; };
|
struct __nat { int __for_bool_; };
|
||||||
|
|
||||||
typedef typename remove_reference<deleter_type>::type& _Dp_reference;
|
#ifndef _LIBCPP_CXX03_LANG
|
||||||
typedef typename remove_reference<typename add_const<deleter_type>::type>::type&
|
typedef __unique_ptr_deleter_sfinae<_Dp> _SFINAE;
|
||||||
_Dp_const_reference;
|
|
||||||
public:
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT
|
|
||||||
: __ptr_(pointer())
|
|
||||||
{
|
|
||||||
static_assert(!is_pointer<deleter_type>::value,
|
|
||||||
"unique_ptr constructed with null function pointer deleter");
|
|
||||||
}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT
|
|
||||||
: __ptr_(pointer())
|
|
||||||
{
|
|
||||||
static_assert(!is_pointer<deleter_type>::value,
|
|
||||||
"unique_ptr constructed with null function pointer deleter");
|
|
||||||
}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY explicit unique_ptr(pointer __p) _NOEXCEPT
|
|
||||||
: __ptr_(_VSTD::move(__p))
|
|
||||||
{
|
|
||||||
static_assert(!is_pointer<deleter_type>::value,
|
|
||||||
"unique_ptr constructed with null function pointer deleter");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
template <bool _Dummy>
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, typename conditional<
|
using _LValRefType =
|
||||||
is_reference<deleter_type>::value,
|
typename __dependent_type<_SFINAE, _Dummy>::__lval_ref_type;
|
||||||
deleter_type,
|
|
||||||
typename add_lvalue_reference<const deleter_type>::type>::type __d)
|
template <bool _Dummy>
|
||||||
_NOEXCEPT
|
using _GoodRValRefType =
|
||||||
|
typename __dependent_type<_SFINAE, _Dummy>::__good_rval_ref_type;
|
||||||
|
|
||||||
|
template <bool _Dummy>
|
||||||
|
using _BadRValRefType =
|
||||||
|
typename __dependent_type<_SFINAE, _Dummy>::__bad_rval_ref_type;
|
||||||
|
|
||||||
|
template <bool _Dummy, class _Deleter = typename __dependent_type<
|
||||||
|
__identity<deleter_type>, _Dummy>::type>
|
||||||
|
using _EnableIfDeleterDefaultConstructible =
|
||||||
|
typename enable_if<is_default_constructible<_Deleter>::value &&
|
||||||
|
!is_pointer<_Deleter>::value>::type;
|
||||||
|
|
||||||
|
template <class _ArgType>
|
||||||
|
using _EnableIfDeleterConstructible =
|
||||||
|
typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type;
|
||||||
|
|
||||||
|
template <class _UPtr, class _Up>
|
||||||
|
using _EnableIfMoveConvertible = typename enable_if<
|
||||||
|
is_convertible<typename _UPtr::pointer, pointer>::value &&
|
||||||
|
!is_array<_Up>::value
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
template <class _UDel>
|
||||||
|
using _EnableIfDeleterConvertible = typename enable_if<
|
||||||
|
(is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) ||
|
||||||
|
(!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value)
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
template <class _UDel>
|
||||||
|
using _EnableIfDeleterAssignable = typename enable_if<
|
||||||
|
is_assignable<_Dp&, _UDel&&>::value
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <bool _Dummy = true,
|
||||||
|
class = _EnableIfDeleterDefaultConstructible<_Dummy>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
constexpr unique_ptr() noexcept : __ptr_(pointer()) {}
|
||||||
|
|
||||||
|
template <bool _Dummy = true,
|
||||||
|
class = _EnableIfDeleterDefaultConstructible<_Dummy>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
constexpr unique_ptr(nullptr_t) noexcept : __ptr_(pointer()) {}
|
||||||
|
|
||||||
|
template <bool _Dummy = true,
|
||||||
|
class = _EnableIfDeleterDefaultConstructible<_Dummy>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
explicit unique_ptr(pointer __p) noexcept : __ptr_(__p) {}
|
||||||
|
|
||||||
|
template <bool _Dummy = true,
|
||||||
|
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy>>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(pointer __p, _LValRefType<_Dummy> __d) noexcept
|
||||||
: __ptr_(__p, __d) {}
|
: __ptr_(__p, __d) {}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, typename remove_reference<deleter_type>::type&& __d)
|
template <bool _Dummy = true,
|
||||||
_NOEXCEPT
|
class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy>>>
|
||||||
: __ptr_(__p, _VSTD::move(__d))
|
|
||||||
{
|
|
||||||
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
|
|
||||||
}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT
|
|
||||||
: __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {}
|
|
||||||
template <class _Up, class _Ep>
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
unique_ptr(unique_ptr<_Up, _Ep>&& __u,
|
unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) noexcept
|
||||||
typename enable_if
|
: __ptr_(__p, _VSTD::move(__d)) {
|
||||||
<
|
static_assert(!is_reference<deleter_type>::value,
|
||||||
!is_array<_Up>::value &&
|
"rvalue deleter bound to reference");
|
||||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value &&
|
}
|
||||||
is_convertible<_Ep, deleter_type>::value &&
|
|
||||||
(
|
template <bool _Dummy = true,
|
||||||
!is_reference<deleter_type>::value ||
|
class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy>>>
|
||||||
is_same<deleter_type, _Ep>::value
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
),
|
unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;
|
||||||
__nat
|
|
||||||
>::type = __nat()) _NOEXCEPT
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(unique_ptr&& __u) noexcept
|
||||||
|
: __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class _Up, class _Ep,
|
||||||
|
class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
|
||||||
|
class = _EnableIfDeleterConvertible<_Ep>
|
||||||
|
>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
|
||||||
: __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {}
|
: __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {}
|
||||||
|
|
||||||
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
|
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
|
||||||
template <class _Up>
|
template <class _Up>
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(auto_ptr<_Up>&& __p,
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
typename enable_if<
|
unique_ptr(auto_ptr<_Up>&& __p,
|
||||||
is_convertible<_Up*, _Tp*>::value &&
|
typename enable_if<is_convertible<_Up*, _Tp*>::value &&
|
||||||
is_same<_Dp, default_delete<_Tp>>::value,
|
is_same<_Dp, default_delete<_Tp>>::value,
|
||||||
__nat
|
__nat>::type = __nat()) _NOEXCEPT
|
||||||
>::type = __nat()) _NOEXCEPT
|
: __ptr_(__p.release()) {}
|
||||||
: __ptr_(__p.release())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
|
||||||
reset(__u.release());
|
reset(__u.release());
|
||||||
__ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
|
__ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Up, class _Ep>
|
template <class _Up, class _Ep,
|
||||||
|
class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
|
||||||
|
class = _EnableIfDeleterAssignable<_Ep>
|
||||||
|
>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
typename enable_if
|
unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
|
||||||
<
|
|
||||||
!is_array<_Up>::value &&
|
|
||||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value &&
|
|
||||||
is_assignable<deleter_type&, _Ep&&>::value,
|
|
||||||
unique_ptr&
|
|
||||||
>::type
|
|
||||||
operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
|
|
||||||
{
|
|
||||||
reset(__u.release());
|
reset(__u.release());
|
||||||
__ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
|
__ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY operator __rv<unique_ptr>()
|
#else // _LIBCPP_CXX03_LANG
|
||||||
|
private:
|
||||||
|
unique_ptr(unique_ptr&);
|
||||||
|
template <class _Up, class _Ep> unique_ptr(unique_ptr<_Up, _Ep>&);
|
||||||
|
|
||||||
|
unique_ptr& operator=(unique_ptr&);
|
||||||
|
template <class _Up, class _Ep> unique_ptr& operator=(unique_ptr<_Up, _Ep>&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr() : __ptr_(pointer())
|
||||||
{
|
{
|
||||||
|
static_assert(!is_pointer<deleter_type>::value,
|
||||||
|
"unique_ptr constructed with null function pointer deleter");
|
||||||
|
static_assert(is_default_constructible<deleter_type>::value,
|
||||||
|
"unique_ptr::deleter_type is not default constructible");
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(nullptr_t) : __ptr_(pointer())
|
||||||
|
{
|
||||||
|
static_assert(!is_pointer<deleter_type>::value,
|
||||||
|
"unique_ptr constructed with null function pointer deleter");
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
explicit unique_ptr(pointer __p)
|
||||||
|
: __ptr_(_VSTD::move(__p)) {
|
||||||
|
static_assert(!is_pointer<deleter_type>::value,
|
||||||
|
"unique_ptr constructed with null function pointer deleter");
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
operator __rv<unique_ptr>() {
|
||||||
return __rv<unique_ptr>(*this);
|
return __rv<unique_ptr>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(__rv<unique_ptr> __u)
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
: __ptr_(__u->release(), _VSTD::forward<deleter_type>(__u->get_deleter())) {}
|
unique_ptr(__rv<unique_ptr> __u)
|
||||||
|
: __ptr_(__u->release(),
|
||||||
|
_VSTD::forward<deleter_type>(__u->get_deleter())) {}
|
||||||
|
|
||||||
template <class _Up, class _Ep>
|
template <class _Up, class _Ep>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
typename enable_if<
|
typename enable_if<
|
||||||
!is_array<_Up>::value &&
|
!is_array<_Up>::value &&
|
||||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value &&
|
is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
|
||||||
|
pointer>::value &&
|
||||||
is_assignable<deleter_type&, _Ep&>::value,
|
is_assignable<deleter_type&, _Ep&>::value,
|
||||||
unique_ptr&
|
unique_ptr&>::type
|
||||||
>::type
|
operator=(unique_ptr<_Up, _Ep> __u) {
|
||||||
operator=(unique_ptr<_Up, _Ep> __u)
|
|
||||||
{
|
|
||||||
reset(__u.release());
|
reset(__u.release());
|
||||||
__ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
|
__ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, deleter_type __d)
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(pointer __p, deleter_type __d)
|
||||||
: __ptr_(_VSTD::move(__p), _VSTD::move(__d)) {}
|
: __ptr_(_VSTD::move(__p), _VSTD::move(__d)) {}
|
||||||
|
#endif // _LIBCPP_CXX03_LANG
|
||||||
|
|
||||||
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
|
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
|
||||||
template <class _Up>
|
template <class _Up>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
typename enable_if<
|
typename enable_if<is_convertible<_Up*, _Tp*>::value &&
|
||||||
is_convertible<_Up*, _Tp*>::value &&
|
|
||||||
is_same<_Dp, default_delete<_Tp> >::value,
|
is_same<_Dp, default_delete<_Tp> >::value,
|
||||||
unique_ptr&
|
unique_ptr&>::type
|
||||||
>::type
|
operator=(auto_ptr<_Up> __p) {
|
||||||
operator=(auto_ptr<_Up> __p)
|
reset(__p.release());
|
||||||
{reset(__p.release()); return *this;}
|
return *this;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
_LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
|
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(nullptr_t) _NOEXCEPT
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
~unique_ptr() { reset(); }
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr& operator=(nullptr_t) _NOEXCEPT {
|
||||||
reset();
|
reset();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY typename add_lvalue_reference<_Tp>::type operator*() const
|
|
||||||
{return *__ptr_.first();}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY pointer operator->() const _NOEXCEPT {return __ptr_.first();}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY pointer get() const _NOEXCEPT {return __ptr_.first();}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _Dp_reference get_deleter() _NOEXCEPT
|
|
||||||
{return __ptr_.second();}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _Dp_const_reference get_deleter() const _NOEXCEPT
|
|
||||||
{return __ptr_.second();}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
|
typename add_lvalue_reference<_Tp>::type
|
||||||
{return __ptr_.first() != nullptr;}
|
operator*() const {
|
||||||
|
return *__ptr_.first();
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
pointer operator->() const _NOEXCEPT {
|
||||||
|
return __ptr_.first();
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
pointer get() const _NOEXCEPT {
|
||||||
|
return __ptr_.first();
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
deleter_type& get_deleter() _NOEXCEPT {
|
||||||
|
return __ptr_.second();
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const deleter_type& get_deleter() const _NOEXCEPT {
|
||||||
|
return __ptr_.second();
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {
|
||||||
|
return __ptr_.first() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY pointer release() _NOEXCEPT
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
pointer release() _NOEXCEPT {
|
||||||
pointer __t = __ptr_.first();
|
pointer __t = __ptr_.first();
|
||||||
__ptr_.first() = pointer();
|
__ptr_.first() = pointer();
|
||||||
return __t;
|
return __t;
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY void reset(pointer __p = pointer()) _NOEXCEPT
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
void reset(pointer __p = pointer()) _NOEXCEPT {
|
||||||
pointer __tmp = __ptr_.first();
|
pointer __tmp = __ptr_.first();
|
||||||
__ptr_.first() = __p;
|
__ptr_.first() = __p;
|
||||||
if (__tmp)
|
if (__tmp)
|
||||||
__ptr_.second()(__tmp);
|
__ptr_.second()(__tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY void swap(unique_ptr& __u) _NOEXCEPT
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{__ptr_.swap(__u.__ptr_);}
|
void swap(unique_ptr& __u) _NOEXCEPT {
|
||||||
|
__ptr_.swap(__u.__ptr_);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class _From, class _ToUnique>
|
||||||
|
struct __check_array_pointer_conversion : is_same<_From, typename _ToUnique::pointer> {};
|
||||||
|
|
||||||
|
template <class _FromElem, class _ToUnique>
|
||||||
|
struct __check_array_pointer_conversion<_FromElem*, _ToUnique>
|
||||||
|
: integral_constant<bool,
|
||||||
|
is_same<_FromElem*, typename _ToUnique::pointer>::value ||
|
||||||
|
(is_same<typename _ToUnique::pointer, typename _ToUnique::element_type*>::value &&
|
||||||
|
is_convertible<_FromElem(*)[], typename _ToUnique::element_type(*)[]>::value)
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
template <class _Tp, class _Dp>
|
template <class _Tp, class _Dp>
|
||||||
class _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
|
class _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef _Tp element_type;
|
typedef _Tp element_type;
|
||||||
typedef _Dp deleter_type;
|
typedef _Dp deleter_type;
|
||||||
typedef typename __pointer_type<_Tp, deleter_type>::type pointer;
|
typedef typename __pointer_type<_Tp, deleter_type>::type pointer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
__compressed_pair<pointer, deleter_type> __ptr_;
|
__compressed_pair<pointer, deleter_type> __ptr_;
|
||||||
|
|
||||||
#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
unique_ptr(unique_ptr&);
|
|
||||||
template <class _Up>
|
|
||||||
unique_ptr(unique_ptr<_Up>&);
|
|
||||||
unique_ptr& operator=(unique_ptr&);
|
|
||||||
template <class _Up>
|
|
||||||
unique_ptr& operator=(unique_ptr<_Up>&);
|
|
||||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
|
|
||||||
struct __nat { int __for_bool_; };
|
struct __nat { int __for_bool_; };
|
||||||
|
|
||||||
typedef typename remove_reference<deleter_type>::type& _Dp_reference;
|
typedef deleter_type& _Dp_reference;
|
||||||
typedef typename remove_reference<typename add_const<deleter_type>::type>::type&
|
typedef typename remove_reference<typename add_const<deleter_type>::type>::type&
|
||||||
_Dp_const_reference;
|
_Dp_const_reference;
|
||||||
public:
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT
|
#ifndef _LIBCPP_CXX03_LANG
|
||||||
: __ptr_(pointer())
|
typedef __unique_ptr_deleter_sfinae<_Dp> _SFINAE;
|
||||||
{
|
|
||||||
static_assert(!is_pointer<deleter_type>::value,
|
template <bool _Dummy>
|
||||||
"unique_ptr constructed with null function pointer deleter");
|
using _LValRefType =
|
||||||
}
|
typename __dependent_type<_SFINAE, _Dummy>::__lval_ref_type;
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT
|
|
||||||
: __ptr_(pointer())
|
template <bool _Dummy>
|
||||||
{
|
using _GoodRValRefType =
|
||||||
static_assert(!is_pointer<deleter_type>::value,
|
typename __dependent_type<_SFINAE, _Dummy>::__good_rval_ref_type;
|
||||||
"unique_ptr constructed with null function pointer deleter");
|
|
||||||
}
|
template <bool _Dummy>
|
||||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
using _BadRValRefType =
|
||||||
template <class _Pp>
|
typename __dependent_type<_SFINAE, _Dummy>::__bad_rval_ref_type;
|
||||||
_LIBCPP_INLINE_VISIBILITY explicit unique_ptr(_Pp __p,
|
|
||||||
typename enable_if<__same_or_less_cv_qualified<_Pp, pointer>::value, __nat>::type = __nat()) _NOEXCEPT
|
template <bool _Dummy, class _Deleter = typename __dependent_type<
|
||||||
: __ptr_(__p)
|
__identity<deleter_type>, _Dummy>::type>
|
||||||
{
|
using _EnableIfDeleterDefaultConstructible =
|
||||||
static_assert(!is_pointer<deleter_type>::value,
|
typename enable_if<is_default_constructible<_Deleter>::value &&
|
||||||
"unique_ptr constructed with null function pointer deleter");
|
!is_pointer<_Deleter>::value>::type;
|
||||||
}
|
|
||||||
|
template <class _ArgType>
|
||||||
|
using _EnableIfDeleterConstructible =
|
||||||
|
typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type;
|
||||||
|
|
||||||
template <class _Pp>
|
template <class _Pp>
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(_Pp __p, typename conditional<
|
using _EnableIfPointerConvertible = typename enable_if<
|
||||||
is_reference<deleter_type>::value,
|
__check_array_pointer_conversion<_Pp, unique_ptr>::value
|
||||||
deleter_type,
|
>::type;
|
||||||
typename add_lvalue_reference<const deleter_type>::type>::type __d,
|
|
||||||
typename enable_if<__same_or_less_cv_qualified<_Pp, pointer>::value, __nat>::type = __nat())
|
template <class _UPtr, class _Up,
|
||||||
_NOEXCEPT
|
class _ElemT = typename _UPtr::element_type>
|
||||||
|
using _EnableIfMoveConvertible = typename enable_if<
|
||||||
|
is_array<_Up>::value &&
|
||||||
|
is_same<pointer, element_type*>::value &&
|
||||||
|
is_same<typename _UPtr::pointer, _ElemT*>::value &&
|
||||||
|
is_convertible<_ElemT(*)[], element_type(*)[]>::value
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
template <class _UDel>
|
||||||
|
using _EnableIfDeleterConvertible = typename enable_if<
|
||||||
|
(is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) ||
|
||||||
|
(!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value)
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
template <class _UDel>
|
||||||
|
using _EnableIfDeleterAssignable = typename enable_if<
|
||||||
|
is_assignable<_Dp&, _UDel&&>::value
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <bool _Dummy = true,
|
||||||
|
class = _EnableIfDeleterDefaultConstructible<_Dummy>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
constexpr unique_ptr() noexcept : __ptr_(pointer()) {}
|
||||||
|
|
||||||
|
template <bool _Dummy = true,
|
||||||
|
class = _EnableIfDeleterDefaultConstructible<_Dummy>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
constexpr unique_ptr(nullptr_t) noexcept : __ptr_(pointer()) {}
|
||||||
|
|
||||||
|
template <class _Pp, bool _Dummy = true,
|
||||||
|
class = _EnableIfDeleterDefaultConstructible<_Dummy>,
|
||||||
|
class = _EnableIfPointerConvertible<_Pp>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
explicit unique_ptr(_Pp __p) noexcept
|
||||||
|
: __ptr_(__p) {}
|
||||||
|
|
||||||
|
template <class _Pp, bool _Dummy = true,
|
||||||
|
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy>>,
|
||||||
|
class = _EnableIfPointerConvertible<_Pp>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) noexcept
|
||||||
: __ptr_(__p, __d) {}
|
: __ptr_(__p, __d) {}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(nullptr_t, typename conditional<
|
template <bool _Dummy = true,
|
||||||
is_reference<deleter_type>::value,
|
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy>>>
|
||||||
deleter_type,
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
typename add_lvalue_reference<const deleter_type>::type>::type __d)
|
unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) noexcept
|
||||||
_NOEXCEPT
|
: __ptr_(nullptr, __d) {}
|
||||||
: __ptr_(pointer(), __d) {}
|
|
||||||
|
|
||||||
template <class _Pp>
|
template <class _Pp, bool _Dummy = true,
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(_Pp __p,
|
class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy>>,
|
||||||
typename remove_reference<deleter_type>::type&& __d,
|
class = _EnableIfPointerConvertible<_Pp>>
|
||||||
typename enable_if<__same_or_less_cv_qualified<_Pp, pointer>::value, __nat>::type = __nat())
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
_NOEXCEPT
|
unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) noexcept
|
||||||
: __ptr_(__p, _VSTD::move(__d))
|
: __ptr_(__p, _VSTD::move(__d)) {
|
||||||
{
|
static_assert(!is_reference<deleter_type>::value,
|
||||||
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
|
"rvalue deleter bound to reference");
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(nullptr_t, typename remove_reference<deleter_type>::type&& __d)
|
template <bool _Dummy = true,
|
||||||
_NOEXCEPT
|
class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy>>>
|
||||||
: __ptr_(pointer(), _VSTD::move(__d))
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) noexcept
|
||||||
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
|
: __ptr_(nullptr, _VSTD::move(__d)) {
|
||||||
|
static_assert(!is_reference<deleter_type>::value,
|
||||||
|
"rvalue deleter bound to reference");
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT
|
template <class _Pp, bool _Dummy = true,
|
||||||
: __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {}
|
class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy>>,
|
||||||
|
class = _EnableIfPointerConvertible<_Pp>>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete;
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
unique_ptr(unique_ptr&& __u) noexcept
|
||||||
|
: __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr& operator=(unique_ptr&& __u) noexcept {
|
||||||
reset(__u.release());
|
reset(__u.release());
|
||||||
__ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
|
__ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Up, class _Ep>
|
template <class _Up, class _Ep,
|
||||||
|
class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
|
||||||
|
class = _EnableIfDeleterConvertible<_Ep>
|
||||||
|
>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
unique_ptr(unique_ptr<_Up, _Ep>&& __u,
|
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||||
typename enable_if
|
: __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {
|
||||||
<
|
}
|
||||||
is_array<_Up>::value &&
|
|
||||||
__same_or_less_cv_qualified<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value
|
|
||||||
&& is_convertible<_Ep, deleter_type>::value &&
|
|
||||||
(
|
|
||||||
!is_reference<deleter_type>::value ||
|
|
||||||
is_same<deleter_type, _Ep>::value
|
|
||||||
),
|
|
||||||
__nat
|
|
||||||
>::type = __nat()
|
|
||||||
) _NOEXCEPT
|
|
||||||
: __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {}
|
|
||||||
|
|
||||||
|
template <class _Up, class _Ep,
|
||||||
template <class _Up, class _Ep>
|
class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
|
||||||
|
class = _EnableIfDeleterAssignable<_Ep>
|
||||||
|
>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
typename enable_if
|
|
||||||
<
|
|
||||||
is_array<_Up>::value &&
|
|
||||||
__same_or_less_cv_qualified<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value &&
|
|
||||||
is_assignable<deleter_type&, _Ep&&>::value,
|
|
||||||
unique_ptr&
|
unique_ptr&
|
||||||
>::type
|
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept {
|
||||||
operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
|
|
||||||
{
|
|
||||||
reset(__u.release());
|
reset(__u.release());
|
||||||
__ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
|
__ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY explicit unique_ptr(pointer __p)
|
#else // _LIBCPP_CXX03_LANG
|
||||||
: __ptr_(__p)
|
private:
|
||||||
{
|
template <class _Up> explicit unique_ptr(_Up);
|
||||||
|
|
||||||
|
unique_ptr(unique_ptr&);
|
||||||
|
template <class _Up> unique_ptr(unique_ptr<_Up>&);
|
||||||
|
|
||||||
|
unique_ptr& operator=(unique_ptr&);
|
||||||
|
template <class _Up> unique_ptr& operator=(unique_ptr<_Up>&);
|
||||||
|
|
||||||
|
template <class _Up>
|
||||||
|
unique_ptr(_Up __u,
|
||||||
|
typename conditional<
|
||||||
|
is_reference<deleter_type>::value, deleter_type,
|
||||||
|
typename add_lvalue_reference<const deleter_type>::type>::type,
|
||||||
|
typename enable_if<is_convertible<_Up, pointer>::value,
|
||||||
|
__nat>::type = __nat());
|
||||||
|
public:
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr() : __ptr_(pointer()) {
|
||||||
|
static_assert(!is_pointer<deleter_type>::value,
|
||||||
|
"unique_ptr constructed with null function pointer deleter");
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(nullptr_t) : __ptr_(pointer()) {
|
||||||
static_assert(!is_pointer<deleter_type>::value,
|
static_assert(!is_pointer<deleter_type>::value,
|
||||||
"unique_ptr constructed with null function pointer deleter");
|
"unique_ptr constructed with null function pointer deleter");
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, deleter_type __d)
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
explicit unique_ptr(pointer __p) : __ptr_(__p) {
|
||||||
|
static_assert(!is_pointer<deleter_type>::value,
|
||||||
|
"unique_ptr constructed with null function pointer deleter");
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(pointer __p, deleter_type __d)
|
||||||
: __ptr_(__p, _VSTD::forward<deleter_type>(__d)) {}
|
: __ptr_(__p, _VSTD::forward<deleter_type>(__d)) {}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(nullptr_t, deleter_type __d)
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr(nullptr_t, deleter_type __d)
|
||||||
: __ptr_(pointer(), _VSTD::forward<deleter_type>(__d)) {}
|
: __ptr_(pointer(), _VSTD::forward<deleter_type>(__d)) {}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY operator __rv<unique_ptr>()
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
operator __rv<unique_ptr>() {
|
||||||
return __rv<unique_ptr>(*this);
|
return __rv<unique_ptr>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr(__rv<unique_ptr> __u)
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
: __ptr_(__u->release(), _VSTD::forward<deleter_type>(__u->get_deleter())) {}
|
unique_ptr(__rv<unique_ptr> __u)
|
||||||
|
: __ptr_(__u->release(),
|
||||||
|
_VSTD::forward<deleter_type>(__u->get_deleter())) {}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(__rv<unique_ptr> __u)
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
unique_ptr& operator=(__rv<unique_ptr> __u) {
|
||||||
reset(__u->release());
|
reset(__u->release());
|
||||||
__ptr_.second() = _VSTD::forward<deleter_type>(__u->get_deleter());
|
__ptr_.second() = _VSTD::forward<deleter_type>(__u->get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
#endif // _LIBCPP_CXX03_LANG
|
||||||
_LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
|
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(nullptr_t) _NOEXCEPT
|
public:
|
||||||
{
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
~unique_ptr() { reset(); }
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
unique_ptr& operator=(nullptr_t) _NOEXCEPT {
|
||||||
reset();
|
reset();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY typename add_lvalue_reference<_Tp>::type operator[](size_t __i) const
|
|
||||||
{return __ptr_.first()[__i];}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY pointer get() const _NOEXCEPT {return __ptr_.first();}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _Dp_reference get_deleter() _NOEXCEPT
|
|
||||||
{return __ptr_.second();}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _Dp_const_reference get_deleter() const _NOEXCEPT
|
|
||||||
{return __ptr_.second();}
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
|
typename add_lvalue_reference<_Tp>::type
|
||||||
{return __ptr_.first() != nullptr;}
|
operator[](size_t __i) const {
|
||||||
|
return __ptr_.first()[__i];
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
pointer get() const _NOEXCEPT {
|
||||||
|
return __ptr_.first();
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY pointer release() _NOEXCEPT
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
{
|
deleter_type& get_deleter() _NOEXCEPT {
|
||||||
|
return __ptr_.second();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const deleter_type& get_deleter() const _NOEXCEPT {
|
||||||
|
return __ptr_.second();
|
||||||
|
}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {
|
||||||
|
return __ptr_.first() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
pointer release() _NOEXCEPT {
|
||||||
pointer __t = __ptr_.first();
|
pointer __t = __ptr_.first();
|
||||||
__ptr_.first() = pointer();
|
__ptr_.first() = pointer();
|
||||||
return __t;
|
return __t;
|
||||||
@@ -2685,40 +2871,29 @@ public:
|
|||||||
|
|
||||||
template <class _Pp>
|
template <class _Pp>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
typename enable_if<__same_or_less_cv_qualified<_Pp, pointer>::value, void>::type
|
typename enable_if<
|
||||||
reset(_Pp __p) _NOEXCEPT
|
__check_array_pointer_conversion<_Pp, unique_ptr>::value
|
||||||
{
|
>::type
|
||||||
|
reset(_Pp __p) _NOEXCEPT {
|
||||||
pointer __tmp = __ptr_.first();
|
pointer __tmp = __ptr_.first();
|
||||||
__ptr_.first() = __p;
|
__ptr_.first() = __p;
|
||||||
if (__tmp)
|
if (__tmp)
|
||||||
__ptr_.second()(__tmp);
|
__ptr_.second()(__tmp);
|
||||||
}
|
}
|
||||||
_LIBCPP_INLINE_VISIBILITY void reset(nullptr_t = nullptr) _NOEXCEPT
|
|
||||||
{
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
void reset(nullptr_t = nullptr) _NOEXCEPT {
|
||||||
pointer __tmp = __ptr_.first();
|
pointer __tmp = __ptr_.first();
|
||||||
__ptr_.first() = nullptr;
|
__ptr_.first() = nullptr;
|
||||||
if (__tmp)
|
if (__tmp)
|
||||||
__ptr_.second()(__tmp);
|
__ptr_.second()(__tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY void swap(unique_ptr& __u) {__ptr_.swap(__u.__ptr_);}
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
private:
|
void swap(unique_ptr& __u) _NOEXCEPT {
|
||||||
|
__ptr_.swap(__u.__ptr_);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
template <class _Up>
|
|
||||||
explicit unique_ptr(_Up);
|
|
||||||
template <class _Up>
|
|
||||||
unique_ptr(_Up __u,
|
|
||||||
typename conditional<
|
|
||||||
is_reference<deleter_type>::value,
|
|
||||||
deleter_type,
|
|
||||||
typename add_lvalue_reference<const deleter_type>::type>::type,
|
|
||||||
typename enable_if
|
|
||||||
<
|
|
||||||
is_convertible<_Up, pointer>::value,
|
|
||||||
__nat
|
|
||||||
>::type = __nat());
|
|
||||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Tp, class _Dp>
|
template <class _Tp, class _Dp>
|
||||||
|
|||||||
@@ -82,31 +82,32 @@ void test_sfinae() {
|
|||||||
static_assert(!std::is_assignable<U, U&>::value, "");
|
static_assert(!std::is_assignable<U, U&>::value, "");
|
||||||
static_assert(!std::is_assignable<U, const U&>::value, "");
|
static_assert(!std::is_assignable<U, const U&>::value, "");
|
||||||
static_assert(!std::is_assignable<U, const U&&>::value, "");
|
static_assert(!std::is_assignable<U, const U&&>::value, "");
|
||||||
static_assert(std::is_assignable<U, U&&>::value, "");
|
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
typedef std::unique_ptr<VT, GenericDeleter> U;
|
typedef std::unique_ptr<VT, GenericDeleter> U;
|
||||||
static_assert(!std::is_assignable<U, U&>::value, "");
|
static_assert(!std::is_assignable<U, U&>::value, "");
|
||||||
static_assert(!std::is_assignable<U, const U&>::value, "");
|
static_assert(!std::is_assignable<U, const U&>::value, "");
|
||||||
static_assert(!std::is_assignable<U, const U&&>::value, "");
|
static_assert(!std::is_assignable<U, const U&&>::value, "");
|
||||||
static_assert(std::is_assignable<U, U&&>::value, "");
|
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
typedef std::unique_ptr<VT, NCDeleter<VT>&> U;
|
typedef std::unique_ptr<VT, NCDeleter<VT>&> U;
|
||||||
static_assert(!std::is_assignable<U, U&>::value, "");
|
static_assert(!std::is_assignable<U, U&>::value, "");
|
||||||
static_assert(!std::is_assignable<U, const U&>::value, "");
|
static_assert(!std::is_assignable<U, const U&>::value, "");
|
||||||
static_assert(!std::is_assignable<U, const U&&>::value, "");
|
static_assert(!std::is_assignable<U, const U&&>::value, "");
|
||||||
static_assert(std::is_assignable<U, U&&>::value, "");
|
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
typedef std::unique_ptr<VT, const NCDeleter<VT>&> U;
|
typedef std::unique_ptr<VT, const NCDeleter<VT>&> U;
|
||||||
static_assert(!std::is_assignable<U, U&>::value, "");
|
static_assert(!std::is_assignable<U, U&>::value, "");
|
||||||
static_assert(!std::is_assignable<U, const U&>::value, "");
|
static_assert(!std::is_assignable<U, const U&>::value, "");
|
||||||
static_assert(!std::is_assignable<U, const U&&>::value, "");
|
static_assert(!std::is_assignable<U, const U&&>::value, "");
|
||||||
static_assert(std::is_assignable<U, U&&>::value, "");
|
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
{
|
{
|
||||||
test_basic</*IsArray*/ false>();
|
test_basic</*IsArray*/ false>();
|
||||||
|
|||||||
@@ -0,0 +1,414 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03
|
||||||
|
|
||||||
|
// <memory>
|
||||||
|
|
||||||
|
// unique_ptr
|
||||||
|
|
||||||
|
// Test unique_ptr converting move ctor
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "unique_ptr_test_helper.h"
|
||||||
|
#include "type_id.h"
|
||||||
|
|
||||||
|
template <int ID = 0>
|
||||||
|
struct GenericDeleter {
|
||||||
|
void operator()(void*) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int ID = 0>
|
||||||
|
struct GenericConvertingDeleter {
|
||||||
|
|
||||||
|
template <int OID>
|
||||||
|
GenericConvertingDeleter(GenericConvertingDeleter<OID>) {}
|
||||||
|
|
||||||
|
template <int OID>
|
||||||
|
GenericConvertingDeleter& operator=(GenericConvertingDeleter<OID> const&) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(void*) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
using EnableIfNotSame = typename std::enable_if<
|
||||||
|
!std::is_same<typename std::decay<T>::type, typename std::decay<U>::type>::value
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
template <template <int> class Templ, class Other>
|
||||||
|
struct is_specialization : std::false_type {};
|
||||||
|
|
||||||
|
template <template <int> class Templ, int ID>
|
||||||
|
struct is_specialization<Templ, Templ<ID> > : std::true_type {};
|
||||||
|
|
||||||
|
template <template <int> class Templ, class Other>
|
||||||
|
using EnableIfSpecialization = typename std::enable_if<
|
||||||
|
is_specialization<Templ, typename std::decay<Other>::type >::value
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
template <int ID>
|
||||||
|
struct TrackingDeleter {
|
||||||
|
TrackingDeleter() : arg_type(&makeArgumentID<>()) {}
|
||||||
|
|
||||||
|
TrackingDeleter(TrackingDeleter const&)
|
||||||
|
: arg_type(&makeArgumentID<TrackingDeleter const&>()) {}
|
||||||
|
|
||||||
|
TrackingDeleter(TrackingDeleter&&)
|
||||||
|
: arg_type(&makeArgumentID<TrackingDeleter &&>()) {}
|
||||||
|
|
||||||
|
template <class T, class = EnableIfSpecialization<TrackingDeleter, T> >
|
||||||
|
TrackingDeleter(T&&) : arg_type(&makeArgumentID<T&&>()) {}
|
||||||
|
|
||||||
|
TrackingDeleter& operator=(TrackingDeleter const&) {
|
||||||
|
arg_type = &makeArgumentID<TrackingDeleter const&>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackingDeleter& operator=(TrackingDeleter &&) {
|
||||||
|
arg_type = &makeArgumentID<TrackingDeleter &&>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class = EnableIfSpecialization<TrackingDeleter, T> >
|
||||||
|
TrackingDeleter& operator=(T&&) {
|
||||||
|
arg_type = &makeArgumentID<T&&>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(void*) const {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
TypeID const* reset() const {
|
||||||
|
TypeID const* tmp = arg_type;
|
||||||
|
arg_type = nullptr;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutable TypeID const* arg_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int ID>
|
||||||
|
struct ConstTrackingDeleter {
|
||||||
|
ConstTrackingDeleter() : arg_type(&makeArgumentID<>()) {}
|
||||||
|
|
||||||
|
ConstTrackingDeleter(ConstTrackingDeleter const&)
|
||||||
|
: arg_type(&makeArgumentID<ConstTrackingDeleter const&>()) {}
|
||||||
|
|
||||||
|
ConstTrackingDeleter(ConstTrackingDeleter&&)
|
||||||
|
: arg_type(&makeArgumentID<ConstTrackingDeleter &&>()) {}
|
||||||
|
|
||||||
|
template <class T, class = EnableIfSpecialization<ConstTrackingDeleter, T> >
|
||||||
|
ConstTrackingDeleter(T&&) : arg_type(&makeArgumentID<T&&>()) {}
|
||||||
|
|
||||||
|
const ConstTrackingDeleter& operator=(ConstTrackingDeleter const&) const {
|
||||||
|
arg_type = &makeArgumentID<ConstTrackingDeleter const&>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConstTrackingDeleter& operator=(ConstTrackingDeleter &&) const {
|
||||||
|
arg_type = &makeArgumentID<ConstTrackingDeleter &&>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class = EnableIfSpecialization<ConstTrackingDeleter, T> >
|
||||||
|
const ConstTrackingDeleter& operator=(T&&) const {
|
||||||
|
arg_type = &makeArgumentID<T&&>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(void*) const {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
TypeID const* reset() const {
|
||||||
|
TypeID const* tmp = arg_type;
|
||||||
|
arg_type = nullptr;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutable TypeID const* arg_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ExpectT, int ID>
|
||||||
|
bool checkArg(TrackingDeleter<ID> const& d) {
|
||||||
|
return d.arg_type && *d.arg_type == makeArgumentID<ExpectT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExpectT, int ID>
|
||||||
|
bool checkArg(ConstTrackingDeleter<ID> const& d) {
|
||||||
|
return d.arg_type && *d.arg_type == makeArgumentID<ExpectT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class From, bool AssignIsConst = false>
|
||||||
|
struct AssignDeleter {
|
||||||
|
AssignDeleter() = default;
|
||||||
|
AssignDeleter(AssignDeleter const&) = default;
|
||||||
|
AssignDeleter(AssignDeleter&&) = default;
|
||||||
|
|
||||||
|
AssignDeleter& operator=(AssignDeleter const&) = delete;
|
||||||
|
AssignDeleter& operator=(AssignDeleter &&) = delete;
|
||||||
|
|
||||||
|
template <class T> AssignDeleter& operator=(T&&) && = delete;
|
||||||
|
template <class T> AssignDeleter& operator=(T&&) const && = delete;
|
||||||
|
|
||||||
|
template <class T, class = typename std::enable_if<
|
||||||
|
std::is_same<T&&, From>::value && !AssignIsConst
|
||||||
|
>::type>
|
||||||
|
AssignDeleter& operator=(T&&) & { return *this; }
|
||||||
|
|
||||||
|
template <class T, class = typename std::enable_if<
|
||||||
|
std::is_same<T&&, From>::value && AssignIsConst
|
||||||
|
>::type>
|
||||||
|
const AssignDeleter& operator=(T&&) const & { return *this; }
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void operator()(T) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class VT, class DDest, class DSource>
|
||||||
|
void doDeleterTest() {
|
||||||
|
using U1 = std::unique_ptr<VT, DDest>;
|
||||||
|
using U2 = std::unique_ptr<VT, DSource>;
|
||||||
|
static_assert(std::is_nothrow_assignable<U1, U2&&>::value, "");
|
||||||
|
typename std::decay<DDest>::type ddest;
|
||||||
|
typename std::decay<DSource>::type dsource;
|
||||||
|
U1 u1(nullptr, ddest);
|
||||||
|
U2 u2(nullptr, dsource);
|
||||||
|
u1 = std::move(u2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool IsArray>
|
||||||
|
void test_sfinae() {
|
||||||
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
|
|
||||||
|
{ // Test that different non-reference deleter types are allowed so long
|
||||||
|
// as they convert to each other.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
|
||||||
|
static_assert(std::is_assignable<U1, U2&&>::value, "");
|
||||||
|
}
|
||||||
|
{ // Test that different non-reference deleter types are disallowed when
|
||||||
|
// they cannot convert.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericDeleter<0> >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericDeleter<1> >;
|
||||||
|
static_assert(!std::is_assignable<U1, U2&&>::value, "");
|
||||||
|
}
|
||||||
|
{ // Test that if the deleter assignment is not valid the assignment operator
|
||||||
|
// SFINAEs.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> const& >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
|
||||||
|
using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
|
||||||
|
using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
|
||||||
|
using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
|
||||||
|
static_assert(!std::is_assignable<U1, U2&&>::value, "");
|
||||||
|
static_assert(!std::is_assignable<U1, U3&&>::value, "");
|
||||||
|
static_assert(!std::is_assignable<U1, U4&&>::value, "");
|
||||||
|
static_assert(!std::is_assignable<U1, U5&&>::value, "");
|
||||||
|
|
||||||
|
using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> const&>;
|
||||||
|
static_assert(std::is_nothrow_assignable<U1C, U1&&>::value, "");
|
||||||
|
}
|
||||||
|
{ // Test that if the deleter assignment is not valid the assignment operator
|
||||||
|
// SFINAEs.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> & >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
|
||||||
|
using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
|
||||||
|
using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
|
||||||
|
using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
|
||||||
|
|
||||||
|
static_assert(std::is_nothrow_assignable<U1, U2&&>::value, "");
|
||||||
|
static_assert(std::is_nothrow_assignable<U1, U3&&>::value, "");
|
||||||
|
static_assert(std::is_nothrow_assignable<U1, U4&&>::value, "");
|
||||||
|
static_assert(std::is_nothrow_assignable<U1, U5&&>::value, "");
|
||||||
|
|
||||||
|
using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> &>;
|
||||||
|
static_assert(std::is_nothrow_assignable<U1C, U1&&>::value, "");
|
||||||
|
}
|
||||||
|
{ // Test that non-reference destination deleters can be assigned
|
||||||
|
// from any source deleter type with a sutible conversion. Including
|
||||||
|
// reference types.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
|
||||||
|
using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> const &>;
|
||||||
|
using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
|
||||||
|
using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> &>;
|
||||||
|
using U6 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
|
||||||
|
static_assert(std::is_assignable<U1, U2&&>::value, "");
|
||||||
|
static_assert(std::is_assignable<U1, U3&&>::value, "");
|
||||||
|
static_assert(std::is_assignable<U1, U4&&>::value, "");
|
||||||
|
static_assert(std::is_assignable<U1, U5&&>::value, "");
|
||||||
|
static_assert(std::is_assignable<U1, U6&&>::value, "");
|
||||||
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
{
|
||||||
|
using Del = GenericDeleter<0>;
|
||||||
|
using AD = AssignDeleter<Del&&>;
|
||||||
|
using ADC = AssignDeleter<Del&&, /*AllowConstAssign*/true>;
|
||||||
|
doDeleterTest<VT, AD, Del>();
|
||||||
|
doDeleterTest<VT, AD&, Del>();
|
||||||
|
doDeleterTest<VT, ADC const&, Del>();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
using Del = GenericDeleter<0>;
|
||||||
|
using AD = AssignDeleter<Del&>;
|
||||||
|
using ADC = AssignDeleter<Del&, /*AllowConstAssign*/true>;
|
||||||
|
doDeleterTest<VT, AD, Del&>();
|
||||||
|
doDeleterTest<VT, AD&, Del&>();
|
||||||
|
doDeleterTest<VT, ADC const&, Del&>();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
using Del = GenericDeleter<0>;
|
||||||
|
using AD = AssignDeleter<Del const&>;
|
||||||
|
using ADC = AssignDeleter<Del const&, /*AllowConstAssign*/true>;
|
||||||
|
doDeleterTest<VT, AD, Del const&>();
|
||||||
|
doDeleterTest<VT, AD&, Del const&>();
|
||||||
|
doDeleterTest<VT, ADC const&, Del const&>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <bool IsArray>
|
||||||
|
void test_noexcept() {
|
||||||
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<const VT> APtr;
|
||||||
|
typedef std::unique_ptr<VT> BPtr;
|
||||||
|
static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<const VT, CDeleter<const VT> > APtr;
|
||||||
|
typedef std::unique_ptr<VT, CDeleter<VT> > BPtr;
|
||||||
|
static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<const VT, NCDeleter<const VT>&> APtr;
|
||||||
|
typedef std::unique_ptr<VT, NCDeleter<const VT>&> BPtr;
|
||||||
|
static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<const VT, const NCConstDeleter<const VT>&> APtr;
|
||||||
|
typedef std::unique_ptr<VT, const NCConstDeleter<const VT>&> BPtr;
|
||||||
|
static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool IsArray>
|
||||||
|
void test_deleter_value_category() {
|
||||||
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
|
using TD1 = TrackingDeleter<1>;
|
||||||
|
using TD2 = TrackingDeleter<2>;
|
||||||
|
TD1 d1;
|
||||||
|
TD2 d2;
|
||||||
|
using CD1 = ConstTrackingDeleter<1>;
|
||||||
|
using CD2 = ConstTrackingDeleter<2>;
|
||||||
|
CD1 cd1;
|
||||||
|
CD2 cd2;
|
||||||
|
|
||||||
|
{ // Test non-reference deleter conversions
|
||||||
|
using U1 = std::unique_ptr<VT, TD1 >;
|
||||||
|
using U2 = std::unique_ptr<VT, TD2 >;
|
||||||
|
U1 u1;
|
||||||
|
U2 u2;
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<TD2&&>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
{ // Test assignment to non-const ref
|
||||||
|
using U1 = std::unique_ptr<VT, TD1& >;
|
||||||
|
using U2 = std::unique_ptr<VT, TD2 >;
|
||||||
|
U1 u1(nullptr, d1);
|
||||||
|
U2 u2;
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<TD2&&>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
{ // Test assignment to const&.
|
||||||
|
using U1 = std::unique_ptr<VT, CD1 const& >;
|
||||||
|
using U2 = std::unique_ptr<VT, CD2 >;
|
||||||
|
U1 u1(nullptr, cd1);
|
||||||
|
U2 u2;
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<CD2&&>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Test assignment from non-const ref
|
||||||
|
using U1 = std::unique_ptr<VT, TD1 >;
|
||||||
|
using U2 = std::unique_ptr<VT, TD2& >;
|
||||||
|
U1 u1;
|
||||||
|
U2 u2(nullptr, d2);
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<TD2&>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
{ // Test assignment from const ref
|
||||||
|
using U1 = std::unique_ptr<VT, TD1 >;
|
||||||
|
using U2 = std::unique_ptr<VT, TD2 const& >;
|
||||||
|
U1 u1;
|
||||||
|
U2 u2(nullptr, d2);
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<TD2 const&>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Test assignment from non-const ref
|
||||||
|
using U1 = std::unique_ptr<VT, TD1& >;
|
||||||
|
using U2 = std::unique_ptr<VT, TD2& >;
|
||||||
|
U1 u1(nullptr, d1);
|
||||||
|
U2 u2(nullptr, d2);
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<TD2&>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
{ // Test assignment from const ref
|
||||||
|
using U1 = std::unique_ptr<VT, TD1& >;
|
||||||
|
using U2 = std::unique_ptr<VT, TD2 const& >;
|
||||||
|
U1 u1(nullptr, d1);
|
||||||
|
U2 u2(nullptr, d2);
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<TD2 const&>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Test assignment from non-const ref
|
||||||
|
using U1 = std::unique_ptr<VT, CD1 const& >;
|
||||||
|
using U2 = std::unique_ptr<VT, CD2 & >;
|
||||||
|
U1 u1(nullptr, cd1);
|
||||||
|
U2 u2(nullptr, cd2);
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<CD2 &>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
{ // Test assignment from const ref
|
||||||
|
using U1 = std::unique_ptr<VT, CD1 const& >;
|
||||||
|
using U2 = std::unique_ptr<VT, CD2 const& >;
|
||||||
|
U1 u1(nullptr, cd1);
|
||||||
|
U2 u2(nullptr, cd2);
|
||||||
|
u1.get_deleter().reset();
|
||||||
|
u1 = std::move(u2);
|
||||||
|
assert(checkArg<CD2 const&>(u1.get_deleter()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
test_sfinae</*IsArray*/false>();
|
||||||
|
test_noexcept<false>();
|
||||||
|
test_deleter_value_category<false>();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_sfinae</*IsArray*/true>();
|
||||||
|
test_noexcept<true>();
|
||||||
|
test_deleter_value_category<true>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,8 +31,6 @@
|
|||||||
#include "deleter_types.h"
|
#include "deleter_types.h"
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
#include "test_workarounds.h" // For TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
|
|
||||||
|
|
||||||
#if defined(_LIBCPP_VERSION) && TEST_STD_VER >= 11
|
#if defined(_LIBCPP_VERSION) && TEST_STD_VER >= 11
|
||||||
_LIBCPP_SAFE_STATIC std::unique_ptr<int> global_static_unique_ptr_single;
|
_LIBCPP_SAFE_STATIC std::unique_ptr<int> global_static_unique_ptr_single;
|
||||||
_LIBCPP_SAFE_STATIC std::unique_ptr<int[]> global_static_unique_ptr_runtime;
|
_LIBCPP_SAFE_STATIC std::unique_ptr<int[]> global_static_unique_ptr_runtime;
|
||||||
@@ -47,7 +45,7 @@ struct NonDefaultDeleter {
|
|||||||
|
|
||||||
template <class ElemType>
|
template <class ElemType>
|
||||||
void test_sfinae() {
|
void test_sfinae() {
|
||||||
#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
|
#if TEST_STD_VER >= 11
|
||||||
{ // the constructor does not participate in overload resultion when
|
{ // the constructor does not participate in overload resultion when
|
||||||
// the deleter is a pointer type
|
// the deleter is a pointer type
|
||||||
using U = std::unique_ptr<ElemType, void (*)(void*)>;
|
using U = std::unique_ptr<ElemType, void (*)(void*)>;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "deleter_types.h"
|
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -139,13 +138,37 @@ void test_basic() {
|
|||||||
assert(A::count == 0);
|
assert(A::count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class VT>
|
||||||
|
void test_noexcept() {
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<VT> U;
|
||||||
|
static_assert(std::is_nothrow_move_constructible<U>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<VT, Deleter<VT> > U;
|
||||||
|
static_assert(std::is_nothrow_move_constructible<U>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<VT, NCDeleter<VT> &> U;
|
||||||
|
static_assert(std::is_nothrow_move_constructible<U>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<VT, const NCConstDeleter<VT> &> U;
|
||||||
|
static_assert(std::is_nothrow_move_constructible<U>::value, "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
{
|
{
|
||||||
test_basic</*IsArray*/ false>();
|
test_basic</*IsArray*/ false>();
|
||||||
test_sfinae<int>();
|
test_sfinae<int>();
|
||||||
|
test_noexcept<int>();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
test_basic</*IsArray*/ true>();
|
test_basic</*IsArray*/ true>();
|
||||||
test_sfinae<int[]>();
|
test_sfinae<int[]>();
|
||||||
|
test_noexcept<int[]>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03
|
||||||
|
|
||||||
|
// <memory>
|
||||||
|
|
||||||
|
// unique_ptr
|
||||||
|
|
||||||
|
// Test unique_ptr converting move ctor
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
|
template <int ID = 0>
|
||||||
|
struct GenericDeleter {
|
||||||
|
void operator()(void*) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int ID = 0>
|
||||||
|
struct GenericConvertingDeleter {
|
||||||
|
template <int OID>
|
||||||
|
GenericConvertingDeleter(GenericConvertingDeleter<OID>) {}
|
||||||
|
void operator()(void*) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool IsArray>
|
||||||
|
void test_sfinae() {
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
|
|
||||||
|
{ // Test that different non-reference deleter types are allowed so long
|
||||||
|
// as they convert to each other.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
|
||||||
|
static_assert(std::is_constructible<U1, U2&&>::value, "");
|
||||||
|
}
|
||||||
|
{ // Test that different non-reference deleter types are disallowed when
|
||||||
|
// they cannot convert.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericDeleter<0> >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericDeleter<1> >;
|
||||||
|
static_assert(!std::is_constructible<U1, U2&&>::value, "");
|
||||||
|
}
|
||||||
|
{ // Test that if the destination deleter is a reference type then only
|
||||||
|
// exact matches are allowed.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> const& >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
|
||||||
|
using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
|
||||||
|
using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
|
||||||
|
using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
|
||||||
|
static_assert(!std::is_constructible<U1, U2&&>::value, "");
|
||||||
|
static_assert(!std::is_constructible<U1, U3&&>::value, "");
|
||||||
|
static_assert(!std::is_constructible<U1, U4&&>::value, "");
|
||||||
|
static_assert(!std::is_constructible<U1, U5&&>::value, "");
|
||||||
|
|
||||||
|
using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> const&>;
|
||||||
|
static_assert(std::is_nothrow_constructible<U1C, U1&&>::value, "");
|
||||||
|
}
|
||||||
|
{ // Test that non-reference destination deleters can be constructed
|
||||||
|
// from any source deleter type with a sutible conversion. Including
|
||||||
|
// reference types.
|
||||||
|
using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
|
||||||
|
using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
|
||||||
|
using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> const &>;
|
||||||
|
using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
|
||||||
|
using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> &>;
|
||||||
|
using U6 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
|
||||||
|
static_assert(std::is_constructible<U1, U2&&>::value, "");
|
||||||
|
static_assert(std::is_constructible<U1, U3&&>::value, "");
|
||||||
|
static_assert(std::is_constructible<U1, U4&&>::value, "");
|
||||||
|
static_assert(std::is_constructible<U1, U5&&>::value, "");
|
||||||
|
static_assert(std::is_constructible<U1, U6&&>::value, "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <bool IsArray>
|
||||||
|
void test_noexcept() {
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<const VT> APtr;
|
||||||
|
typedef std::unique_ptr<VT> BPtr;
|
||||||
|
static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<const VT, CDeleter<const VT> > APtr;
|
||||||
|
typedef std::unique_ptr<VT, CDeleter<VT> > BPtr;
|
||||||
|
static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<const VT, NCDeleter<const VT>&> APtr;
|
||||||
|
typedef std::unique_ptr<VT, NCDeleter<const VT>&> BPtr;
|
||||||
|
static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<const VT, const NCConstDeleter<const VT>&> APtr;
|
||||||
|
typedef std::unique_ptr<VT, const NCConstDeleter<const VT>&> BPtr;
|
||||||
|
static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
test_sfinae</*IsArray*/false>();
|
||||||
|
test_noexcept<false>();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_sfinae</*IsArray*/true>();
|
||||||
|
test_noexcept<true>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -77,4 +77,7 @@ void test_sfinae() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() { test_sfinae(); }
|
|
||||||
|
int main() {
|
||||||
|
test_sfinae();
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "deleter_types.h"
|
#include "test_macros.h"
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
// test converting move ctor. Should only require a MoveConstructible deleter, or if
|
// test converting move ctor. Should only require a MoveConstructible deleter, or if
|
||||||
@@ -135,7 +135,34 @@ void test_sfinae() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_noexcept() {
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<A> APtr;
|
||||||
|
typedef std::unique_ptr<B> BPtr;
|
||||||
|
static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<A, Deleter<A> > APtr;
|
||||||
|
typedef std::unique_ptr<B, Deleter<B> > BPtr;
|
||||||
|
static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<A, NCDeleter<A>&> APtr;
|
||||||
|
typedef std::unique_ptr<B, NCDeleter<A>&> BPtr;
|
||||||
|
static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<A, const NCConstDeleter<A>&> APtr;
|
||||||
|
typedef std::unique_ptr<B, const NCConstDeleter<A>&> BPtr;
|
||||||
|
static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
{
|
||||||
|
test_sfinae();
|
||||||
|
test_noexcept();
|
||||||
|
}
|
||||||
{
|
{
|
||||||
typedef std::unique_ptr<A> APtr;
|
typedef std::unique_ptr<A> APtr;
|
||||||
typedef std::unique_ptr<B> BPtr;
|
typedef std::unique_ptr<B> BPtr;
|
||||||
@@ -218,5 +245,4 @@ int main() {
|
|||||||
}
|
}
|
||||||
checkNoneAlive();
|
checkNoneAlive();
|
||||||
}
|
}
|
||||||
test_sfinae();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,25 +17,14 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "deleter_types.h"
|
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
#include "test_workarounds.h" // For TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
|
|
||||||
|
|
||||||
// default unique_ptr ctor should only require default Deleter ctor
|
#if defined(_LIBCPP_VERSION) && TEST_STD_VER >= 11
|
||||||
class DefaultDeleter {
|
_LIBCPP_SAFE_STATIC std::unique_ptr<int> global_static_unique_ptr_single(nullptr);
|
||||||
int state_;
|
_LIBCPP_SAFE_STATIC std::unique_ptr<int[]> global_static_unique_ptr_runtime(nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
DefaultDeleter(DefaultDeleter&);
|
|
||||||
DefaultDeleter& operator=(DefaultDeleter&);
|
|
||||||
|
|
||||||
public:
|
|
||||||
DefaultDeleter() : state_(5) {}
|
|
||||||
|
|
||||||
int state() const { return state_; }
|
|
||||||
|
|
||||||
void operator()(void*) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
struct NonDefaultDeleter {
|
struct NonDefaultDeleter {
|
||||||
@@ -46,15 +35,6 @@ struct NonDefaultDeleter {
|
|||||||
|
|
||||||
template <class VT>
|
template <class VT>
|
||||||
void test_basic() {
|
void test_basic() {
|
||||||
{
|
|
||||||
std::unique_ptr<VT> p(nullptr);
|
|
||||||
assert(p.get() == 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::unique_ptr<VT, DefaultDeleter> p(nullptr);
|
|
||||||
assert(p.get() == 0);
|
|
||||||
assert(p.get_deleter().state() == 5);
|
|
||||||
}
|
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
using U1 = std::unique_ptr<VT>;
|
using U1 = std::unique_ptr<VT>;
|
||||||
@@ -65,11 +45,20 @@ void test_basic() {
|
|||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
std::unique_ptr<VT> p(nullptr);
|
||||||
|
assert(p.get() == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::unique_ptr<VT, NCDeleter<VT> > p(nullptr);
|
||||||
|
assert(p.get() == 0);
|
||||||
|
assert(p.get_deleter().state() == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class VT>
|
template <class VT>
|
||||||
void test_sfinae() {
|
void test_sfinae() {
|
||||||
#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
|
#if TEST_STD_VER >= 11
|
||||||
{ // the constructor does not participate in overload resultion when
|
{ // the constructor does not participate in overload resultion when
|
||||||
// the deleter is a pointer type
|
// the deleter is a pointer type
|
||||||
using U = std::unique_ptr<VT, void (*)(void*)>;
|
using U = std::unique_ptr<VT, void (*)(void*)>;
|
||||||
|
|||||||
@@ -35,8 +35,6 @@
|
|||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
#include "test_workarounds.h" // For TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
|
|
||||||
|
|
||||||
// unique_ptr(pointer) ctor should only require default Deleter ctor
|
// unique_ptr(pointer) ctor should only require default Deleter ctor
|
||||||
|
|
||||||
template <bool IsArray>
|
template <bool IsArray>
|
||||||
@@ -47,8 +45,14 @@ void test_pointer() {
|
|||||||
{
|
{
|
||||||
using U1 = std::unique_ptr<ValueT>;
|
using U1 = std::unique_ptr<ValueT>;
|
||||||
using U2 = std::unique_ptr<ValueT, Deleter<ValueT> >;
|
using U2 = std::unique_ptr<ValueT, Deleter<ValueT> >;
|
||||||
|
|
||||||
|
// Test for noexcept
|
||||||
static_assert(std::is_nothrow_constructible<U1, A*>::value, "");
|
static_assert(std::is_nothrow_constructible<U1, A*>::value, "");
|
||||||
static_assert(std::is_nothrow_constructible<U2, A*>::value, "");
|
static_assert(std::is_nothrow_constructible<U2, A*>::value, "");
|
||||||
|
|
||||||
|
// Test for explicit
|
||||||
|
static_assert(!std::is_convertible<A*, U1>::value, "");
|
||||||
|
static_assert(!std::is_convertible<A*, U2>::value, "");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@@ -103,7 +107,7 @@ struct GenericDeleter {
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void test_sfinae() {
|
void test_sfinae() {
|
||||||
#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
|
#if TEST_STD_VER >= 11
|
||||||
{ // the constructor does not participate in overload resultion when
|
{ // the constructor does not participate in overload resultion when
|
||||||
// the deleter is a pointer type
|
// the deleter is a pointer type
|
||||||
using U = std::unique_ptr<T, void (*)(void*)>;
|
using U = std::unique_ptr<T, void (*)(void*)>;
|
||||||
|
|||||||
@@ -19,17 +19,11 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "test_workarounds.h"
|
|
||||||
|
|
||||||
struct Deleter {
|
struct Deleter {
|
||||||
void operator()(int* p) const { delete p; }
|
void operator()(int* p) const { delete p; }
|
||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
#if defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
|
// expected-error@+1 {{call to deleted constructor of 'std::unique_ptr<int, const Deleter &>}}
|
||||||
// expected-error@memory:* {{static_assert failed "rvalue deleter bound to reference"}}
|
|
||||||
#else
|
|
||||||
// expected-error@+2 {{call to deleted constructor of 'std::unique_ptr<int, const Deleter &>}}
|
|
||||||
#endif
|
|
||||||
std::unique_ptr<int, const Deleter&> s((int*)nullptr, Deleter());
|
std::unique_ptr<int, const Deleter&> s((int*)nullptr, Deleter());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,6 @@
|
|||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
#include "test_workarounds.h" // For TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
|
|
||||||
|
|
||||||
bool my_free_called = false;
|
bool my_free_called = false;
|
||||||
|
|
||||||
void my_free(void*) { my_free_called = true; }
|
void my_free(void*) { my_free_called = true; }
|
||||||
@@ -56,7 +54,7 @@ struct NoCopyMoveDeleter : DeleterBase {
|
|||||||
|
|
||||||
template <bool IsArray>
|
template <bool IsArray>
|
||||||
void test_sfinae() {
|
void test_sfinae() {
|
||||||
#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
|
#if TEST_STD_VER >= 11
|
||||||
typedef typename std::conditional<!IsArray, int, int[]>::type VT;
|
typedef typename std::conditional<!IsArray, int, int[]>::type VT;
|
||||||
{
|
{
|
||||||
using D = CopyOnlyDeleter;
|
using D = CopyOnlyDeleter;
|
||||||
@@ -137,13 +135,13 @@ void test_noexcept() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_sfinae_runtime() {
|
void test_sfinae_runtime() {
|
||||||
#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
|
#if TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
using D = CopyOnlyDeleter;
|
using D = CopyOnlyDeleter;
|
||||||
using U = std::unique_ptr<A[], D>;
|
using U = std::unique_ptr<A[], D>;
|
||||||
static_assert(std::is_constructible<U, A*, D const&>::value, "");
|
static_assert(std::is_nothrow_constructible<U, A*, D const&>::value, "");
|
||||||
static_assert(std::is_constructible<U, A*, D&>::value, "");
|
static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
|
||||||
static_assert(std::is_constructible<U, A*, D&&>::value, "");
|
static_assert(std::is_nothrow_constructible<U, A*, D&&>::value, "");
|
||||||
|
|
||||||
static_assert(!std::is_constructible<U, B*, D const&>::value, "");
|
static_assert(!std::is_constructible<U, B*, D const&>::value, "");
|
||||||
static_assert(!std::is_constructible<U, B*, D&>::value, "");
|
static_assert(!std::is_constructible<U, B*, D&>::value, "");
|
||||||
@@ -158,7 +156,7 @@ void test_sfinae_runtime() {
|
|||||||
using U = std::unique_ptr<A[], D>;
|
using U = std::unique_ptr<A[], D>;
|
||||||
static_assert(!std::is_constructible<U, A*, D const&>::value, "");
|
static_assert(!std::is_constructible<U, A*, D const&>::value, "");
|
||||||
static_assert(!std::is_constructible<U, A*, D&>::value, "");
|
static_assert(!std::is_constructible<U, A*, D&>::value, "");
|
||||||
static_assert(std::is_constructible<U, A*, D&&>::value, "");
|
static_assert(std::is_nothrow_constructible<U, A*, D&&>::value, "");
|
||||||
|
|
||||||
static_assert(!std::is_constructible<U, B*, D const&>::value, "");
|
static_assert(!std::is_constructible<U, B*, D const&>::value, "");
|
||||||
static_assert(!std::is_constructible<U, B*, D&>::value, "");
|
static_assert(!std::is_constructible<U, B*, D&>::value, "");
|
||||||
@@ -181,7 +179,7 @@ void test_sfinae_runtime() {
|
|||||||
using D = NoCopyMoveDeleter;
|
using D = NoCopyMoveDeleter;
|
||||||
using U = std::unique_ptr<A[], D&>;
|
using U = std::unique_ptr<A[], D&>;
|
||||||
static_assert(!std::is_constructible<U, A*, D const&>::value, "");
|
static_assert(!std::is_constructible<U, A*, D const&>::value, "");
|
||||||
static_assert(std::is_constructible<U, A*, D&>::value, "");
|
static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
|
||||||
static_assert(!std::is_constructible<U, A*, D&&>::value, "");
|
static_assert(!std::is_constructible<U, A*, D&&>::value, "");
|
||||||
static_assert(!std::is_constructible<U, A*, const D&&>::value, "");
|
static_assert(!std::is_constructible<U, A*, const D&&>::value, "");
|
||||||
|
|
||||||
@@ -193,8 +191,8 @@ void test_sfinae_runtime() {
|
|||||||
{
|
{
|
||||||
using D = NoCopyMoveDeleter;
|
using D = NoCopyMoveDeleter;
|
||||||
using U = std::unique_ptr<A[], const D&>;
|
using U = std::unique_ptr<A[], const D&>;
|
||||||
static_assert(std::is_constructible<U, A*, D const&>::value, "");
|
static_assert(std::is_nothrow_constructible<U, A*, D const&>::value, "");
|
||||||
static_assert(std::is_constructible<U, A*, D&>::value, "");
|
static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
|
||||||
static_assert(!std::is_constructible<U, A*, D&&>::value, "");
|
static_assert(!std::is_constructible<U, A*, D&&>::value, "");
|
||||||
static_assert(!std::is_constructible<U, A*, const D&&>::value, "");
|
static_assert(!std::is_constructible<U, A*, const D&&>::value, "");
|
||||||
|
|
||||||
@@ -291,15 +289,38 @@ void test_basic_single() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool IsArray>
|
||||||
|
void test_nullptr() {
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
typedef typename std::conditional<!IsArray, A, A[]>::type VT;
|
||||||
|
{
|
||||||
|
std::unique_ptr<VT, Deleter<VT> > u(nullptr, Deleter<VT>{});
|
||||||
|
assert(u.get() == nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
NCDeleter<VT> d;
|
||||||
|
std::unique_ptr<VT, NCDeleter<VT>& > u(nullptr, d);
|
||||||
|
assert(u.get() == nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
NCConstDeleter<VT> d;
|
||||||
|
std::unique_ptr<VT, NCConstDeleter<VT> const& > u(nullptr, d);
|
||||||
|
assert(u.get() == nullptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
{
|
{
|
||||||
test_basic</*IsArray*/ false>();
|
test_basic</*IsArray*/ false>();
|
||||||
|
test_nullptr<false>();
|
||||||
test_basic_single();
|
test_basic_single();
|
||||||
test_sfinae<false>();
|
test_sfinae<false>();
|
||||||
test_noexcept<false>();
|
test_noexcept<false>();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
test_basic</*IsArray*/ true>();
|
test_basic</*IsArray*/ true>();
|
||||||
|
test_nullptr<true>();
|
||||||
test_sfinae<true>();
|
test_sfinae<true>();
|
||||||
test_sfinae_runtime();
|
test_sfinae_runtime();
|
||||||
test_noexcept<true>();
|
test_noexcept<true>();
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ void test_basic() {
|
|||||||
Deleter d;
|
Deleter d;
|
||||||
assert(d.state() == 0);
|
assert(d.state() == 0);
|
||||||
{
|
{
|
||||||
std::unique_ptr<T, Deleter&> p(0, d);
|
std::unique_ptr<T, Deleter&> p(nullptr, d);
|
||||||
assert(p.get() == 0);
|
assert(p.get() == nullptr);
|
||||||
assert(&p.get_deleter() == &d);
|
assert(&p.get_deleter() == &d);
|
||||||
}
|
}
|
||||||
assert(d.state() == 0);
|
assert(d.state() == 0);
|
||||||
|
|||||||
@@ -16,12 +16,20 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
template <bool IsArray>
|
template <bool IsArray>
|
||||||
void test_basic() {
|
void test_basic() {
|
||||||
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
const int expect_alive = IsArray ? 3 : 1;
|
const int expect_alive = IsArray ? 3 : 1;
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{
|
||||||
|
using U = std::unique_ptr<VT>;
|
||||||
|
U u; ((void)u);
|
||||||
|
ASSERT_NOEXCEPT(u.release());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
std::unique_ptr<VT> p(newValue<VT>(expect_alive));
|
std::unique_ptr<VT> p(newValue<VT>(expect_alive));
|
||||||
assert(A::count == expect_alive);
|
assert(A::count == expect_alive);
|
||||||
|
|||||||
@@ -16,22 +16,20 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
template <bool IsArray>
|
template <bool IsArray>
|
||||||
void test_basic() {
|
void test_reset_pointer() {
|
||||||
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
const int expect_alive = IsArray ? 3 : 1;
|
const int expect_alive = IsArray ? 3 : 1;
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
std::unique_ptr<VT> p(newValue<VT>(expect_alive));
|
using U = std::unique_ptr<VT>;
|
||||||
assert(A::count == expect_alive);
|
U u; ((void)u);
|
||||||
A* i = p.get();
|
ASSERT_NOEXCEPT(u.reset((A*)nullptr));
|
||||||
assert(i != nullptr);
|
|
||||||
p.reset();
|
|
||||||
assert(A::count == 0);
|
|
||||||
assert(p.get() == 0);
|
|
||||||
}
|
}
|
||||||
assert(A::count == 0);
|
#endif
|
||||||
{
|
{
|
||||||
std::unique_ptr<VT> p(newValue<VT>(expect_alive));
|
std::unique_ptr<VT> p(newValue<VT>(expect_alive));
|
||||||
assert(A::count == expect_alive);
|
assert(A::count == expect_alive);
|
||||||
@@ -41,11 +39,79 @@ void test_basic() {
|
|||||||
assert(A::count == (expect_alive * 2));
|
assert(A::count == (expect_alive * 2));
|
||||||
p.reset(new_value);
|
p.reset(new_value);
|
||||||
assert(A::count == expect_alive);
|
assert(A::count == expect_alive);
|
||||||
|
assert(p.get() == new_value);
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
{
|
||||||
|
std::unique_ptr<const VT> p(newValue<const VT>(expect_alive));
|
||||||
|
assert(A::count == expect_alive);
|
||||||
|
const A* i = p.get();
|
||||||
|
assert(i != nullptr);
|
||||||
|
A* new_value = newValue<VT>(expect_alive);
|
||||||
|
assert(A::count == (expect_alive * 2));
|
||||||
|
p.reset(new_value);
|
||||||
|
assert(A::count == expect_alive);
|
||||||
|
assert(p.get() == new_value);
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool IsArray>
|
||||||
|
void test_reset_nullptr() {
|
||||||
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
|
const int expect_alive = IsArray ? 3 : 1;
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{
|
||||||
|
using U = std::unique_ptr<VT>;
|
||||||
|
U u; ((void)u);
|
||||||
|
ASSERT_NOEXCEPT(u.reset(nullptr));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
std::unique_ptr<VT> p(newValue<VT>(expect_alive));
|
||||||
|
assert(A::count == expect_alive);
|
||||||
|
A* i = p.get();
|
||||||
|
assert(i != nullptr);
|
||||||
|
p.reset(nullptr);
|
||||||
|
assert(A::count == 0);
|
||||||
|
assert(p.get() == nullptr);
|
||||||
|
}
|
||||||
|
assert(A::count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <bool IsArray>
|
||||||
|
void test_reset_no_arg() {
|
||||||
|
typedef typename std::conditional<IsArray, A[], A>::type VT;
|
||||||
|
const int expect_alive = IsArray ? 3 : 1;
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{
|
||||||
|
using U = std::unique_ptr<VT>;
|
||||||
|
U u; ((void)u);
|
||||||
|
ASSERT_NOEXCEPT(u.reset());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
std::unique_ptr<VT> p(newValue<VT>(expect_alive));
|
||||||
|
assert(A::count == expect_alive);
|
||||||
|
A* i = p.get();
|
||||||
|
assert(i != nullptr);
|
||||||
|
p.reset();
|
||||||
|
assert(A::count == 0);
|
||||||
|
assert(p.get() == nullptr);
|
||||||
}
|
}
|
||||||
assert(A::count == 0);
|
assert(A::count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
test_basic</*IsArray*/ false>();
|
{
|
||||||
test_basic<true>();
|
test_reset_pointer</*IsArray*/ false>();
|
||||||
|
test_reset_nullptr<false>();
|
||||||
|
test_reset_no_arg<false>();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_reset_pointer</*IsArray*/true>();
|
||||||
|
test_reset_nullptr<true>();
|
||||||
|
test_reset_no_arg<true>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
#include "unique_ptr_test_helper.h"
|
#include "unique_ptr_test_helper.h"
|
||||||
|
|
||||||
struct TT {
|
struct TT {
|
||||||
@@ -51,6 +52,13 @@ template <bool IsArray>
|
|||||||
void test_basic() {
|
void test_basic() {
|
||||||
typedef typename std::conditional<IsArray, TT[], TT>::type VT;
|
typedef typename std::conditional<IsArray, TT[], TT>::type VT;
|
||||||
const int expect_alive = IsArray ? 5 : 1;
|
const int expect_alive = IsArray ? 5 : 1;
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
{
|
||||||
|
using U = std::unique_ptr<VT, Deleter<VT> >;
|
||||||
|
U u; ((void)u);
|
||||||
|
ASSERT_NOEXCEPT(u.swap(u));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
TT* p1 = newValueInit<VT>(expect_alive, 1);
|
TT* p1 = newValueInit<VT>(expect_alive, 1);
|
||||||
std::unique_ptr<VT, Deleter<VT> > s1(p1, Deleter<VT>(1));
|
std::unique_ptr<VT, Deleter<VT> > s1(p1, Deleter<VT>(1));
|
||||||
|
|||||||
@@ -193,6 +193,10 @@ public:
|
|||||||
|
|
||||||
CDeleter() : state_(0) {}
|
CDeleter() : state_(0) {}
|
||||||
explicit CDeleter(int s) : state_(s) {}
|
explicit CDeleter(int s) : state_(s) {}
|
||||||
|
template <class U>
|
||||||
|
CDeleter(const CDeleter<U>& d)
|
||||||
|
: state_(d.state()) {}
|
||||||
|
|
||||||
~CDeleter() {assert(state_ >= 0); state_ = -1;}
|
~CDeleter() {assert(state_ >= 0); state_ = -1;}
|
||||||
|
|
||||||
int state() const {return state_;}
|
int state() const {return state_;}
|
||||||
|
|||||||
@@ -17,12 +17,4 @@
|
|||||||
# define TEST_WORKAROUND_C1XX_BROKEN_NULLPTR_CONVERSION_OPERATOR
|
# define TEST_WORKAROUND_C1XX_BROKEN_NULLPTR_CONVERSION_OPERATOR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME(EricWF): Remove this. This macro guards tests for upcoming changes
|
|
||||||
// and fixes to unique_ptr. Until the changes have been implemented in trunk
|
|
||||||
// the tests have to be disabled. However the tests have been left in until
|
|
||||||
// then so they can be used by other standard libraries.
|
|
||||||
#if defined(_LIBCPP_VERSION)
|
|
||||||
# define TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // SUPPORT_TEST_WORKAROUNDS_H
|
#endif // SUPPORT_TEST_WORKAROUNDS_H
|
||||||
|
|||||||
@@ -448,7 +448,7 @@
|
|||||||
<tr><td><a href="http://wg21.link/LWG2794">2794</a></td><td>Missing requirements for allocator pointers</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2794">2794</a></td><td>Missing requirements for allocator pointers</td><td>Kona</td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2795">2795</a></td><td>§[global.functions] provides incorrect example of ADL use</td><td>Kona</td><td>Complete</td></tr>
|
<tr><td><a href="http://wg21.link/LWG2795">2795</a></td><td>§[global.functions] provides incorrect example of ADL use</td><td>Kona</td><td>Complete</td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2796">2796</a></td><td>tuple should be a literal type</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2796">2796</a></td><td>tuple should be a literal type</td><td>Kona</td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2801">2801</a></td><td>Default-constructibility of unique_ptr</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2801">2801</a></td><td>Default-constructibility of unique_ptr</td><td>Kona</td><td>Complete</td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2802">2802</a></td><td>shared_ptr constructor requirements for a deleter</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2802">2802</a></td><td>shared_ptr constructor requirements for a deleter</td><td>Kona</td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2804">2804</a></td><td>Unconditional constexpr default constructor for istream_iterator</td><td>Kona</td><td>Complete</td></tr>
|
<tr><td><a href="http://wg21.link/LWG2804">2804</a></td><td>Unconditional constexpr default constructor for istream_iterator</td><td>Kona</td><td>Complete</td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2806">2806</a></td><td>Base class of bad_optional_access</td><td>Kona</td><td>Complete</td></tr>
|
<tr><td><a href="http://wg21.link/LWG2806">2806</a></td><td>Base class of bad_optional_access</td><td>Kona</td><td>Complete</td></tr>
|
||||||
@@ -478,7 +478,7 @@
|
|||||||
<tr><td><a href="http://wg21.link/LWG2900">2900</a></td><td>The copy and move constructors of optional are not constexpr</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2900">2900</a></td><td>The copy and move constructors of optional are not constexpr</td><td>Kona</td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2903">2903</a></td><td>The form of initialization for the emplace-constructors is not specified</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2903">2903</a></td><td>The form of initialization for the emplace-constructors is not specified</td><td>Kona</td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2904">2904</a></td><td>Make variant move-assignment more exception safe</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2904">2904</a></td><td>Make variant move-assignment more exception safe</td><td>Kona</td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2905">2905</a></td><td>is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2905">2905</a></td><td>is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible</td><td>Kona</td><td>Complete</td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2908">2908</a></td><td>The less-than operator for shared pointers could do more</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2908">2908</a></td><td>The less-than operator for shared pointers could do more</td><td>Kona</td><td></td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2911">2911</a></td><td>An is_aggregate type trait is needed</td><td>Kona</td><td>Complete</td></tr>
|
<tr><td><a href="http://wg21.link/LWG2911">2911</a></td><td>An is_aggregate type trait is needed</td><td>Kona</td><td>Complete</td></tr>
|
||||||
<tr><td><a href="http://wg21.link/LWG2921">2921</a></td><td>packaged_task and type-erased allocators</td><td>Kona</td><td></td></tr>
|
<tr><td><a href="http://wg21.link/LWG2921">2921</a></td><td>packaged_task and type-erased allocators</td><td>Kona</td><td></td></tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user