forked from OSchip/llvm-project
[libcxx] Fix __compressed_pair so it doesn't copy the argument multiple times, and add constexpr.
Summary: __compressed_pair takes and passes it's constructor arguments by value. This causes arguments to be moved 3 times instead of once. This patch addresses that issue and fixes `constexpr` on the constructors. I would rather have this fix than D27564, and I'm fairly confident it's not ABI breaking but I'm not 100% sure. I prefer this solution because it removes a lot of code and makes the implementation *much* smaller. Reviewers: mclow.lists, K-ballo Reviewed By: K-ballo Subscribers: K-ballo, cfe-commits Differential Revision: https://reviews.llvm.org/D27565 llvm-svn: 300140
This commit is contained in:
parent
6fd4bc6b22
commit
c88580c400
|
@ -1402,7 +1402,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
|
|||
const key_equal& __eql,
|
||||
const allocator_type& __a)
|
||||
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
|
||||
__p1_(__node_allocator(__a)),
|
||||
__p1_(__second_tag(), __node_allocator(__a)),
|
||||
__p2_(0, __hf),
|
||||
__p3_(1.0f, __eql)
|
||||
{
|
||||
|
@ -1411,7 +1411,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
|
|||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
|
||||
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
|
||||
__p1_(__node_allocator(__a)),
|
||||
__p1_(__second_tag(), __node_allocator(__a)),
|
||||
__p2_(0),
|
||||
__p3_(1.0f)
|
||||
{
|
||||
|
@ -1423,7 +1423,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
|
|||
__bucket_list_deleter(allocator_traits<__pointer_allocator>::
|
||||
select_on_container_copy_construction(
|
||||
__u.__bucket_list_.get_deleter().__alloc()), 0)),
|
||||
__p1_(allocator_traits<__node_allocator>::
|
||||
__p1_(__second_tag(), allocator_traits<__node_allocator>::
|
||||
select_on_container_copy_construction(__u.__node_alloc())),
|
||||
__p2_(0, __u.hash_function()),
|
||||
__p3_(__u.__p3_)
|
||||
|
@ -1434,7 +1434,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
|||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
|
||||
const allocator_type& __a)
|
||||
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
|
||||
__p1_(__node_allocator(__a)),
|
||||
__p1_(__second_tag(), __node_allocator(__a)),
|
||||
__p2_(0, __u.hash_function()),
|
||||
__p3_(__u.__p3_)
|
||||
{
|
||||
|
@ -1468,7 +1468,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
|||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
|
||||
const allocator_type& __a)
|
||||
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
|
||||
__p1_(__node_allocator(__a)),
|
||||
__p1_(__second_tag(), __node_allocator(__a)),
|
||||
__p2_(0, _VSTD::move(__u.hash_function())),
|
||||
__p3_(_VSTD::move(__u.__p3_))
|
||||
{
|
||||
|
|
|
@ -653,7 +653,7 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
|
|||
#include <tuple>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
#include <cassert>
|
||||
#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
|
||||
# include <atomic>
|
||||
#endif
|
||||
|
@ -2070,307 +2070,174 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
template <class _T1, class _T2, bool = is_same<typename remove_cv<_T1>::type,
|
||||
typename remove_cv<_T2>::type>::value,
|
||||
bool = is_empty<_T1>::value
|
||||
&& !__libcpp_is_final<_T1>::value,
|
||||
bool = is_empty<_T2>::value
|
||||
&& !__libcpp_is_final<_T2>::value
|
||||
>
|
||||
struct __libcpp_compressed_pair_switch;
|
||||
template <class _Tp, int _Idx,
|
||||
bool _CanBeEmptyBase =
|
||||
is_empty<_Tp>::value && !__libcpp_is_final<_Tp>::value>
|
||||
struct __compressed_pair_elem {
|
||||
typedef _Tp _ParamT;
|
||||
typedef _Tp& reference;
|
||||
typedef const _Tp& const_reference;
|
||||
|
||||
template <class _T1, class _T2, bool IsSame>
|
||||
struct __libcpp_compressed_pair_switch<_T1, _T2, IsSame, false, false> {enum {value = 0};};
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
__compressed_pair_elem() = default;
|
||||
|
||||
template <class _T1, class _T2, bool IsSame>
|
||||
struct __libcpp_compressed_pair_switch<_T1, _T2, IsSame, true, false> {enum {value = 1};};
|
||||
template <class _Up, class = typename enable_if<
|
||||
!is_same<__compressed_pair_elem, _Up>::value>::type>
|
||||
_LIBCPP_CONSTEXPR explicit
|
||||
__compressed_pair_elem(_Up&& __u)
|
||||
: __value_(_VSTD::forward<_Up>(__u)){};
|
||||
|
||||
template <class _T1, class _T2, bool IsSame>
|
||||
struct __libcpp_compressed_pair_switch<_T1, _T2, IsSame, false, true> {enum {value = 2};};
|
||||
template <class... _Args, size_t... _Indexes>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
__compressed_pair_elem(piecewise_construct_t, tuple<_Args...> __args,
|
||||
__tuple_indices<_Indexes...>)
|
||||
: __value_(_VSTD::forward<_Args>(_VSTD::get<_Indexes>(__args))...) {}
|
||||
#else
|
||||
__compressed_pair_elem() : __value_() {}
|
||||
__compressed_pair_elem(_ParamT __p) : __value_(std::forward<_ParamT>(__p)) {}
|
||||
#endif
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct __libcpp_compressed_pair_switch<_T1, _T2, false, true, true> {enum {value = 3};};
|
||||
reference __get() _NOEXCEPT { return __value_; }
|
||||
const_reference __get() const _NOEXCEPT { return __value_; }
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct __libcpp_compressed_pair_switch<_T1, _T2, true, true, true> {enum {value = 1};};
|
||||
|
||||
template <class _T1, class _T2, unsigned = __libcpp_compressed_pair_switch<_T1, _T2>::value>
|
||||
class __libcpp_compressed_pair_imp;
|
||||
|
||||
template <class _T1, class _T2>
|
||||
class __libcpp_compressed_pair_imp<_T1, _T2, 0>
|
||||
{
|
||||
private:
|
||||
_T1 __first_;
|
||||
_T2 __second_;
|
||||
public:
|
||||
typedef _T1 _T1_param;
|
||||
typedef _T2 _T2_param;
|
||||
|
||||
typedef typename remove_reference<_T1>::type& _T1_reference;
|
||||
typedef typename remove_reference<_T2>::type& _T2_reference;
|
||||
|
||||
typedef typename remove_reference<typename add_const<_T1>::type>::type& _T1_const_reference;
|
||||
typedef typename remove_reference<typename add_const<_T2>::type>::type& _T2_const_reference;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() : __first_(), __second_() {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T1_param __t1)
|
||||
: __first_(_VSTD::forward<_T1_param>(__t1)), __second_() {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T2_param __t2)
|
||||
: __first_(), __second_(_VSTD::forward<_T2_param>(__t2)) {}
|
||||
_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2)
|
||||
: __first_(_VSTD::forward<_T1_param>(__t1)), __second_(_VSTD::forward<_T2_param>(__t2)) {}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__libcpp_compressed_pair_imp(piecewise_construct_t,
|
||||
tuple<_Args1...> __first_args,
|
||||
tuple<_Args2...> __second_args,
|
||||
__tuple_indices<_I1...>,
|
||||
__tuple_indices<_I2...>)
|
||||
: __first_(_VSTD::forward<_Args1>(_VSTD::get<_I1>(__first_args))...),
|
||||
__second_(_VSTD::forward<_Args2>(_VSTD::get<_I2>(__second_args))...)
|
||||
{}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_reference first() _NOEXCEPT {return __first_;}
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return __first_;}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_reference second() _NOEXCEPT {return __second_;}
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return __second_;}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY void swap(__libcpp_compressed_pair_imp& __x)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_T1>::value &&
|
||||
__is_nothrow_swappable<_T2>::value)
|
||||
{
|
||||
using _VSTD::swap;
|
||||
swap(__first_, __x.__first_);
|
||||
swap(__second_, __x.__second_);
|
||||
}
|
||||
_Tp __value_;
|
||||
};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
class __libcpp_compressed_pair_imp<_T1, _T2, 1>
|
||||
: private _T1
|
||||
{
|
||||
private:
|
||||
_T2 __second_;
|
||||
public:
|
||||
typedef _T1 _T1_param;
|
||||
typedef _T2 _T2_param;
|
||||
template <class _Tp, int _Idx>
|
||||
struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp {
|
||||
typedef _Tp _ParamT;
|
||||
typedef _Tp& reference;
|
||||
typedef const _Tp& const_reference;
|
||||
typedef _Tp __value_type;
|
||||
|
||||
typedef _T1& _T1_reference;
|
||||
typedef typename remove_reference<_T2>::type& _T2_reference;
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
__compressed_pair_elem() = default;
|
||||
|
||||
typedef const _T1& _T1_const_reference;
|
||||
typedef typename remove_reference<typename add_const<_T2>::type>::type&
|
||||
_T2_const_reference;
|
||||
template <class _Up, class = typename enable_if<
|
||||
!is_same<__compressed_pair_elem, _Up>::value>::type>
|
||||
_LIBCPP_CONSTEXPR explicit
|
||||
__compressed_pair_elem(_Up&& __u)
|
||||
: __value_type(_VSTD::forward<_Up>(__u)){};
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() : __second_() {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T1_param __t1)
|
||||
: _T1(_VSTD::forward<_T1_param>(__t1)), __second_() {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T2_param __t2)
|
||||
: __second_(_VSTD::forward<_T2_param>(__t2)) {}
|
||||
_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2)
|
||||
: _T1(_VSTD::forward<_T1_param>(__t1)), __second_(_VSTD::forward<_T2_param>(__t2)) {}
|
||||
template <class... _Args, size_t... _Indexes>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
__compressed_pair_elem(piecewise_construct_t, tuple<_Args...> __args,
|
||||
__tuple_indices<_Indexes...>)
|
||||
: __value_type(_VSTD::forward<_Args>(_VSTD::get<_Indexes>(__args))...) {}
|
||||
#else
|
||||
__compressed_pair_elem() : __value_type() {}
|
||||
__compressed_pair_elem(_ParamT __p)
|
||||
: __value_type(std::forward<_ParamT>(__p)) {}
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__libcpp_compressed_pair_imp(piecewise_construct_t,
|
||||
tuple<_Args1...> __first_args,
|
||||
tuple<_Args2...> __second_args,
|
||||
__tuple_indices<_I1...>,
|
||||
__tuple_indices<_I2...>)
|
||||
: _T1(_VSTD::forward<_Args1>(_VSTD::get<_I1>(__first_args))...),
|
||||
__second_(_VSTD::forward<_Args2>(_VSTD::get<_I2>(__second_args))...)
|
||||
{}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_reference first() _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return *this;}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_reference second() _NOEXCEPT {return __second_;}
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return __second_;}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY void swap(__libcpp_compressed_pair_imp& __x)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_T1>::value &&
|
||||
__is_nothrow_swappable<_T2>::value)
|
||||
{
|
||||
using _VSTD::swap;
|
||||
swap(__second_, __x.__second_);
|
||||
}
|
||||
reference __get() _NOEXCEPT { return *this; }
|
||||
const_reference __get() const _NOEXCEPT { return *this; }
|
||||
};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
class __libcpp_compressed_pair_imp<_T1, _T2, 2>
|
||||
: private _T2
|
||||
{
|
||||
private:
|
||||
_T1 __first_;
|
||||
public:
|
||||
typedef _T1 _T1_param;
|
||||
typedef _T2 _T2_param;
|
||||
|
||||
typedef typename remove_reference<_T1>::type& _T1_reference;
|
||||
typedef _T2& _T2_reference;
|
||||
|
||||
typedef typename remove_reference<typename add_const<_T1>::type>::type&
|
||||
_T1_const_reference;
|
||||
typedef const _T2& _T2_const_reference;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() : __first_() {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T1_param __t1)
|
||||
: __first_(_VSTD::forward<_T1_param>(__t1)) {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T2_param __t2)
|
||||
: _T2(_VSTD::forward<_T2_param>(__t2)), __first_() {}
|
||||
_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2)
|
||||
_NOEXCEPT_(is_nothrow_move_constructible<_T1>::value &&
|
||||
is_nothrow_move_constructible<_T2>::value)
|
||||
: _T2(_VSTD::forward<_T2_param>(__t2)), __first_(_VSTD::forward<_T1_param>(__t1)) {}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__libcpp_compressed_pair_imp(piecewise_construct_t,
|
||||
tuple<_Args1...> __first_args,
|
||||
tuple<_Args2...> __second_args,
|
||||
__tuple_indices<_I1...>,
|
||||
__tuple_indices<_I2...>)
|
||||
: _T2(_VSTD::forward<_Args2>(_VSTD::get<_I2>(__second_args))...),
|
||||
__first_(_VSTD::forward<_Args1>(_VSTD::get<_I1>(__first_args))...)
|
||||
|
||||
{}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_reference first() _NOEXCEPT {return __first_;}
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return __first_;}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_reference second() _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return *this;}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY void swap(__libcpp_compressed_pair_imp& __x)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_T1>::value &&
|
||||
__is_nothrow_swappable<_T2>::value)
|
||||
{
|
||||
using _VSTD::swap;
|
||||
swap(__first_, __x.__first_);
|
||||
}
|
||||
};
|
||||
// Tag used to construct the second element of the compressed pair.
|
||||
struct __second_tag {};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
class __libcpp_compressed_pair_imp<_T1, _T2, 3>
|
||||
: private _T1,
|
||||
private _T2
|
||||
{
|
||||
class __compressed_pair : private __compressed_pair_elem<_T1, 0>,
|
||||
private __compressed_pair_elem<_T2, 1> {
|
||||
typedef __compressed_pair_elem<_T1, 0> _Base1;
|
||||
typedef __compressed_pair_elem<_T2, 1> _Base2;
|
||||
|
||||
// NOTE: This static assert should never fire because __compressed_pair
|
||||
// is *almost never* used in a scenario where it's possible for T1 == T2.
|
||||
// (The exception is std::function where it is possible that the function
|
||||
// object and the allocator have the same type).
|
||||
static_assert(!is_same<_T1, _T2>::value,
|
||||
"__compressed_pair cannot be instantated when T1 and T2 are the same type; "
|
||||
"The current implementation is NOT ABI-compatible with the previous "
|
||||
"implementation for this configuration");
|
||||
|
||||
public:
|
||||
typedef _T1 _T1_param;
|
||||
typedef _T2 _T2_param;
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__compressed_pair() = default;
|
||||
|
||||
typedef _T1& _T1_reference;
|
||||
typedef _T2& _T2_reference;
|
||||
template <class _Tp, typename enable_if<!is_same<typename decay<_Tp>::type,
|
||||
__compressed_pair>::value,
|
||||
bool>::type = true>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr explicit
|
||||
__compressed_pair(_Tp&& __t)
|
||||
: _Base1(std::forward<_Tp>(__t)), _Base2() {}
|
||||
|
||||
typedef const _T1& _T1_const_reference;
|
||||
typedef const _T2& _T2_const_reference;
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
__compressed_pair(__second_tag, _Tp&& __t)
|
||||
: _Base1(), _Base2(std::forward<_Tp>(__t)) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T1_param __t1)
|
||||
: _T1(_VSTD::forward<_T1_param>(__t1)) {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T2_param __t2)
|
||||
: _T2(_VSTD::forward<_T2_param>(__t2)) {}
|
||||
_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2)
|
||||
: _T1(_VSTD::forward<_T1_param>(__t1)), _T2(_VSTD::forward<_T2_param>(__t2)) {}
|
||||
template <class _U1, class _U2>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
__compressed_pair(_U1&& __t1, _U2&& __t2)
|
||||
: _Base1(std::forward<_U1>(__t1)), _Base2(std::forward<_U2>(__t2)) {}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
template <class... _Args1, class... _Args2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
__compressed_pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args,
|
||||
tuple<_Args2...> __second_args)
|
||||
: _Base1(__pc, _VSTD::move(__first_args),
|
||||
typename __make_tuple_indices<sizeof...(_Args1)>::type()),
|
||||
_Base2(__pc, _VSTD::move(__second_args),
|
||||
typename __make_tuple_indices<sizeof...(_Args2)>::type()) {}
|
||||
|
||||
template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__libcpp_compressed_pair_imp(piecewise_construct_t,
|
||||
tuple<_Args1...> __first_args,
|
||||
tuple<_Args2...> __second_args,
|
||||
__tuple_indices<_I1...>,
|
||||
__tuple_indices<_I2...>)
|
||||
: _T1(_VSTD::forward<_Args1>(_VSTD::get<_I1>(__first_args))...),
|
||||
_T2(_VSTD::forward<_Args2>(_VSTD::get<_I2>(__second_args))...)
|
||||
{}
|
||||
#else
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__compressed_pair() {}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
_LIBCPP_INLINE_VISIBILITY explicit
|
||||
__compressed_pair(_T1 __t1) : _Base1(_VSTD::forward<_T1>(__t1)) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_reference first() _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__compressed_pair(__second_tag, _T2 __t2)
|
||||
: _Base1(), _Base2(_VSTD::forward<_T2>(__t2)) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_reference second() _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__compressed_pair(_T1 __t1, _T2 __t2)
|
||||
: _Base1(_VSTD::forward<_T1>(__t1)), _Base2(_VSTD::forward<_T2>(__t2)) {}
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY void swap(__libcpp_compressed_pair_imp&)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_T1>::value &&
|
||||
__is_nothrow_swappable<_T2>::value)
|
||||
{
|
||||
}
|
||||
};
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename _Base1::reference first() _NOEXCEPT {
|
||||
return static_cast<_Base1&>(*this).__get();
|
||||
}
|
||||
|
||||
template <class _T1, class _T2>
|
||||
class __compressed_pair
|
||||
: private __libcpp_compressed_pair_imp<_T1, _T2>
|
||||
{
|
||||
typedef __libcpp_compressed_pair_imp<_T1, _T2> base;
|
||||
public:
|
||||
typedef typename base::_T1_param _T1_param;
|
||||
typedef typename base::_T2_param _T2_param;
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename _Base1::const_reference first() const _NOEXCEPT {
|
||||
return static_cast<_Base1 const&>(*this).__get();
|
||||
}
|
||||
|
||||
typedef typename base::_T1_reference _T1_reference;
|
||||
typedef typename base::_T2_reference _T2_reference;
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename _Base2::reference second() _NOEXCEPT {
|
||||
return static_cast<_Base2&>(*this).__get();
|
||||
}
|
||||
|
||||
typedef typename base::_T1_const_reference _T1_const_reference;
|
||||
typedef typename base::_T2_const_reference _T2_const_reference;
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename _Base2::const_reference second() const _NOEXCEPT {
|
||||
return static_cast<_Base2 const&>(*this).__get();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __compressed_pair() {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __compressed_pair(_T1_param __t1)
|
||||
: base(_VSTD::forward<_T1_param>(__t1)) {}
|
||||
_LIBCPP_INLINE_VISIBILITY explicit __compressed_pair(_T2_param __t2)
|
||||
: base(_VSTD::forward<_T2_param>(__t2)) {}
|
||||
_LIBCPP_INLINE_VISIBILITY __compressed_pair(_T1_param __t1, _T2_param __t2)
|
||||
: base(_VSTD::forward<_T1_param>(__t1), _VSTD::forward<_T2_param>(__t2)) {}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class... _Args1, class... _Args2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__compressed_pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args,
|
||||
tuple<_Args2...> __second_args)
|
||||
: base(__pc, _VSTD::move(__first_args), _VSTD::move(__second_args),
|
||||
typename __make_tuple_indices<sizeof...(_Args1)>::type(),
|
||||
typename __make_tuple_indices<sizeof...(_Args2) >::type())
|
||||
{}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_reference first() _NOEXCEPT {return base::first();}
|
||||
_LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return base::first();}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_reference second() _NOEXCEPT {return base::second();}
|
||||
_LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return base::second();}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY void swap(__compressed_pair& __x)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_T1>::value &&
|
||||
__is_nothrow_swappable<_T2>::value)
|
||||
{base::swap(__x);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void swap(__compressed_pair& __x)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_T1>::value &&
|
||||
__is_nothrow_swappable<_T2>::value)
|
||||
{
|
||||
using std::swap;
|
||||
swap(first(), __x.first());
|
||||
swap(second(), __x.second());
|
||||
}
|
||||
};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_T1>::value &&
|
||||
__is_nothrow_swappable<_T2>::value)
|
||||
{__x.swap(__y);}
|
||||
void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_T1>::value &&
|
||||
__is_nothrow_swappable<_T2>::value) {
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
// __same_or_less_cv_qualified
|
||||
|
||||
|
@ -2401,7 +2268,7 @@ struct __same_or_less_cv_qualified<_Ptr1, _Ptr2, false>
|
|||
template <class _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS default_delete
|
||||
{
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR default_delete() _NOEXCEPT = default;
|
||||
#else
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR default_delete() _NOEXCEPT {}
|
||||
|
@ -2421,7 +2288,7 @@ template <class _Tp>
|
|||
struct _LIBCPP_TEMPLATE_VIS default_delete<_Tp[]>
|
||||
{
|
||||
public:
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR default_delete() _NOEXCEPT = default;
|
||||
#else
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR default_delete() _NOEXCEPT {}
|
||||
|
|
|
@ -1511,7 +1511,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __
|
|||
#else
|
||||
_NOEXCEPT
|
||||
#endif
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
__get_db()->__insert_c(this);
|
||||
|
@ -1582,7 +1582,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s)
|
|||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
_LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr");
|
||||
__init(__s, traits_type::length(__s));
|
||||
|
@ -1605,7 +1605,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_
|
|||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n, const _Allocator& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
_LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr");
|
||||
__init(__s, __n);
|
||||
|
@ -1616,7 +1616,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_
|
|||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str)
|
||||
: __r_(__alloc_traits::select_on_container_copy_construction(__str.__alloc()))
|
||||
: __r_(__second_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc()))
|
||||
{
|
||||
if (!__str.__is_long())
|
||||
__r_.first().__r = __str.__r_.first().__r;
|
||||
|
@ -1630,7 +1630,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st
|
|||
template <class _CharT, class _Traits, class _Allocator>
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(
|
||||
const basic_string& __str, const allocator_type& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
if (!__str.__is_long())
|
||||
__r_.first().__r = __str.__r_.first().__r;
|
||||
|
@ -1664,7 +1664,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str)
|
|||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, const allocator_type& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
if (__str.__is_long() && __a != __str.__alloc()) // copy, not move
|
||||
__init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size());
|
||||
|
@ -1719,7 +1719,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __
|
|||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c, const _Allocator& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
__init(__n, __c);
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
@ -1731,7 +1731,7 @@ template <class _CharT, class _Traits, class _Allocator>
|
|||
basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str,
|
||||
size_type __pos, size_type __n,
|
||||
const _Allocator& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
size_type __str_sz = __str.size();
|
||||
if (__pos > __str_sz)
|
||||
|
@ -1746,7 +1746,7 @@ template <class _CharT, class _Traits, class _Allocator>
|
|||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos,
|
||||
const _Allocator& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
size_type __str_sz = __str.size();
|
||||
if (__pos > __str_sz)
|
||||
|
@ -1762,7 +1762,7 @@ template <class _Tp>
|
|||
basic_string<_CharT, _Traits, _Allocator>::basic_string(
|
||||
const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a,
|
||||
typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type *)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
__self_view __sv = __self_view(__t).substr(__pos, __n);
|
||||
__init(__sv.data(), __sv.size());
|
||||
|
@ -1784,7 +1784,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv)
|
|||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv, const _Allocator& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
__init(__sv.data(), __sv.size());
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
@ -1866,7 +1866,7 @@ template<class _InputIterator>
|
|||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last,
|
||||
const allocator_type& __a)
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
__init(__first, __last);
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
@ -1889,10 +1889,10 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(
|
|||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
|
||||
basic_string<_CharT, _Traits, _Allocator>::basic_string(
|
||||
initializer_list<_CharT> __il, const _Allocator& __a)
|
||||
|
||||
: __r_(__a)
|
||||
: __r_(__second_tag(), __a)
|
||||
{
|
||||
__init(__il.begin(), __il.end());
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
|
|
@ -15,24 +15,25 @@
|
|||
|
||||
// default unique_ptr ctor should require default Deleter ctor
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include "test_macros.h"
|
||||
|
||||
class Deleter
|
||||
{
|
||||
// expected-error@memory:* {{base class 'Deleter' has private default constructor}}
|
||||
// expected-note@memory:* + {{in instantiation of member function}}
|
||||
Deleter() {} // expected-note {{implicitly declared private here}}
|
||||
class Deleter {
|
||||
Deleter() {}
|
||||
|
||||
public:
|
||||
Deleter(Deleter&) {}
|
||||
Deleter& operator=(Deleter&) { return *this; }
|
||||
|
||||
Deleter(Deleter&) {}
|
||||
Deleter& operator=(Deleter&) { return *this; }
|
||||
|
||||
void operator()(void*) const {}
|
||||
void operator()(void*) const {}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::unique_ptr<int[], Deleter> p;
|
||||
int main() {
|
||||
#if TEST_STD_VER >= 11
|
||||
// expected-error@memory:* {{call to implicitly-deleted default constructor}}
|
||||
// expected-note@memory:* {{implicitly deleted because base class 'Deleter' has an inaccessible default constructor}}
|
||||
#else
|
||||
// expected-error@memory:* {{base class 'Deleter' has private default constructor}}
|
||||
#endif
|
||||
std::unique_ptr<int[], Deleter> p; // expected-note {{requested here}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue