forked from OSchip/llvm-project
Implement the std::pair parts of "Improving pair and tuple". Completes N4387.
llvm-svn: 276605
This commit is contained in:
parent
126de5d4b4
commit
4927c29577
libcxx
|
@ -146,6 +146,12 @@ template <class ..._Tp> class _LIBCPP_TYPE_VIS_ONLY tuple;
|
|||
|
||||
template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {};
|
||||
|
||||
template <class ..._Tp>
|
||||
class _LIBCPP_TYPE_VIS_ONLY tuple_size<tuple<_Tp...> >
|
||||
: public integral_constant<size_t, sizeof...(_Tp)>
|
||||
{
|
||||
};
|
||||
|
||||
template <size_t _Ip, class ..._Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
typename tuple_element<_Ip, tuple<_Tp...> >::type&
|
||||
|
@ -431,8 +437,48 @@ struct __tuple_assignable<_Tp, _Up, true, true>
|
|||
>
|
||||
{};
|
||||
|
||||
|
||||
template <size_t _Ip, class ..._Tp>
|
||||
class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, tuple<_Tp...> >
|
||||
{
|
||||
public:
|
||||
typedef typename tuple_element<_Ip, __tuple_types<_Tp...> >::type type;
|
||||
};
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
template <size_t _Ip, class ..._Tp>
|
||||
using tuple_element_t = typename tuple_element <_Ip, _Tp...>::type;
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <bool _IsTuple, class _SizeTrait, size_t _Expected>
|
||||
struct __tuple_like_with_size_imp : false_type {};
|
||||
|
||||
template <class _SizeTrait, size_t _Expected>
|
||||
struct __tuple_like_with_size_imp<true, _SizeTrait, _Expected>
|
||||
: integral_constant<bool, _SizeTrait::value == _Expected> {};
|
||||
|
||||
template <class _Tuple, size_t _ExpectedSize,
|
||||
class _RawTuple = typename __uncvref<_Tuple>::type>
|
||||
using __tuple_like_with_size = __tuple_like_with_size_imp<
|
||||
__tuple_like<_RawTuple>::value,
|
||||
tuple_size<_RawTuple>, _ExpectedSize
|
||||
>;
|
||||
|
||||
struct _LIBCPP_TYPE_VIS __check_tuple_constructor_fail {
|
||||
template <class ...>
|
||||
static constexpr bool __enable_default() { return false; }
|
||||
template <class ...>
|
||||
static constexpr bool __enable_explicit() { return false; }
|
||||
template <class ...>
|
||||
static constexpr bool __enable_implicit() { return false; }
|
||||
template <class ...>
|
||||
static constexpr bool __enable_assign() { return false; }
|
||||
};
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___TUPLE
|
||||
|
|
|
@ -150,27 +150,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
// tuple_size
|
||||
|
||||
template <class ..._Tp>
|
||||
class _LIBCPP_TYPE_VIS_ONLY tuple_size<tuple<_Tp...> >
|
||||
: public integral_constant<size_t, sizeof...(_Tp)>
|
||||
{
|
||||
};
|
||||
|
||||
// tuple_element
|
||||
|
||||
template <size_t _Ip, class ..._Tp>
|
||||
class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, tuple<_Tp...> >
|
||||
{
|
||||
public:
|
||||
typedef typename tuple_element<_Ip, __tuple_types<_Tp...> >::type type;
|
||||
};
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
template <size_t _Ip, class ..._Tp>
|
||||
using tuple_element_t = typename tuple_element <_Ip, _Tp...>::type;
|
||||
#endif
|
||||
|
||||
// __tuple_leaf
|
||||
|
||||
|
@ -489,27 +468,7 @@ struct __tuple_impl<__tuple_indices<_Indx...>, _Tp...>
|
|||
}
|
||||
};
|
||||
|
||||
template <bool _IsTuple, class _SizeTrait, size_t _Expected>
|
||||
struct __tuple_like_with_size_imp : false_type {};
|
||||
|
||||
template <class _SizeTrait, size_t _Expected>
|
||||
struct __tuple_like_with_size_imp<true, _SizeTrait, _Expected>
|
||||
: integral_constant<bool, _SizeTrait::value == _Expected> {};
|
||||
|
||||
template <class _Tuple, size_t _ExpectedSize,
|
||||
class _RawTuple = typename __uncvref<_Tuple>::type>
|
||||
using __tuple_like_with_size = __tuple_like_with_size_imp<
|
||||
__tuple_like<_RawTuple>::value,
|
||||
tuple_size<_RawTuple>, _ExpectedSize
|
||||
>;
|
||||
|
||||
|
||||
struct _LIBCPP_TYPE_VIS __check_tuple_constructor_fail {
|
||||
template <class ...>
|
||||
static constexpr bool __enable_explicit() { return false; }
|
||||
template <class ...>
|
||||
static constexpr bool __enable_implicit() { return false; }
|
||||
};
|
||||
|
||||
template <class ..._Tp>
|
||||
class _LIBCPP_TYPE_VIS_ONLY tuple
|
||||
|
@ -531,6 +490,11 @@ class _LIBCPP_TYPE_VIS_ONLY tuple
|
|||
template <class _Dummy>
|
||||
struct _CheckArgsConstructor<true, _Dummy>
|
||||
{
|
||||
template <class ..._Args>
|
||||
static constexpr bool __enable_default() {
|
||||
return __all<is_default_constructible<_Args>::value...>::value;
|
||||
}
|
||||
|
||||
template <class ..._Args>
|
||||
static constexpr bool __enable_explicit() {
|
||||
return
|
||||
|
@ -641,7 +605,7 @@ class _LIBCPP_TYPE_VIS_ONLY tuple
|
|||
public:
|
||||
|
||||
template <bool _Dummy = true, class = typename enable_if<
|
||||
__all<__dependent_type<is_default_constructible<_Tp>, _Dummy>::value...>::value
|
||||
_CheckArgsConstructor<_Dummy>::template __enable_default<_Tp...>()
|
||||
>::type>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR tuple()
|
||||
|
@ -1362,6 +1326,9 @@ template <class ..._Tp, class _Alloc>
|
|||
struct _LIBCPP_TYPE_VIS_ONLY uses_allocator<tuple<_Tp...>, _Alloc>
|
||||
: true_type {};
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _T1, class _T2>
|
||||
template <class... _Args1, class... _Args2, size_t ..._I1, size_t ..._I2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -1372,8 +1339,7 @@ pair<_T1, _T2>::pair(piecewise_construct_t,
|
|||
second(_VSTD::forward<_Args2>(_VSTD::get<_I2>(__second_args))...)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _Tp>
|
||||
|
|
|
@ -291,6 +291,7 @@ extern const piecewise_construct_t piecewise_construct;// = piecewise_construct_
|
|||
constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t();
|
||||
#endif
|
||||
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct _LIBCPP_TYPE_VIS_ONLY pair
|
||||
{
|
||||
|
@ -300,28 +301,6 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
|
|||
_T1 first;
|
||||
_T2 second;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS
|
||||
template <bool _Dummy = true, class = typename enable_if<
|
||||
__dependent_type<is_default_constructible<_T1>, _Dummy>::value &&
|
||||
__dependent_type<is_default_constructible<_T2>, _Dummy>::value
|
||||
>::type>
|
||||
#endif
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR pair() : first(), second() {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(const _T1& __x, const _T2& __y)
|
||||
: first(__x), second(__y) {}
|
||||
|
||||
template<class _U1, class _U2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(const pair<_U1, _U2>& __p
|
||||
#ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE
|
||||
,typename enable_if<is_convertible<const _U1&, _T1>::value &&
|
||||
is_convertible<const _U2&, _T2>::value>::type* = 0
|
||||
#endif
|
||||
)
|
||||
: first(__p.first), second(__p.second) {}
|
||||
|
||||
#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair(const pair& __p)
|
||||
|
@ -348,23 +327,172 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
|
|||
// Use the implicitly declared copy constructor in C++03
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_CXX03_LANG)
|
||||
typedef typename conditional<
|
||||
is_copy_assignable<_T1>::value
|
||||
&& is_copy_assignable<_T2>::value,
|
||||
pair, __nat
|
||||
>::type _CopyAssignT;
|
||||
typedef typename conditional<
|
||||
is_move_assignable<_T1>::value
|
||||
&& is_move_assignable<_T2>::value,
|
||||
pair, __nat
|
||||
>::type _MoveAssignT;
|
||||
#else
|
||||
typedef pair _CopyAssignT;
|
||||
#endif
|
||||
#ifdef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair() : first(), second() {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair& operator=(_CopyAssignT const& __p)
|
||||
pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {}
|
||||
|
||||
template <class _U1, class _U2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair& operator=(pair const& __p) {
|
||||
first = __p.first;
|
||||
second = __p.second;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
template <bool _Val>
|
||||
using _EnableB = typename enable_if<_Val, bool>::type;
|
||||
|
||||
struct _CheckArgs {
|
||||
template <class _U1, class _U2>
|
||||
static constexpr bool __enable_default() {
|
||||
return is_default_constructible<_U1>::value
|
||||
&& is_default_constructible<_U2>::value;
|
||||
}
|
||||
|
||||
template <class _U1, class _U2>
|
||||
static constexpr bool __enable_explicit() {
|
||||
return is_constructible<first_type, _U1>::value
|
||||
&& is_constructible<second_type, _U2>::value
|
||||
&& (!is_convertible<_U1, first_type>::value
|
||||
|| !is_convertible<_U2, second_type>::value);
|
||||
}
|
||||
|
||||
template <class _U1, class _U2>
|
||||
static constexpr bool __enable_implicit() {
|
||||
return is_constructible<first_type, _U1>::value
|
||||
&& is_constructible<second_type, _U2>::value
|
||||
&& is_convertible<_U1, first_type>::value
|
||||
&& is_convertible<_U2, second_type>::value;
|
||||
}
|
||||
};
|
||||
|
||||
template <bool _MaybeEnable>
|
||||
using _CheckArgsDep = typename conditional<
|
||||
_MaybeEnable, _CheckArgs, __check_tuple_constructor_fail>::type;
|
||||
|
||||
struct _CheckTupleLikeConstructor {
|
||||
template <class _Tuple>
|
||||
static constexpr bool __enable_implicit() {
|
||||
return __tuple_convertible<_Tuple, pair>::value;
|
||||
}
|
||||
|
||||
template <class _Tuple>
|
||||
static constexpr bool __enable_explicit() {
|
||||
return __tuple_constructible<_Tuple, pair>::value
|
||||
&& !__tuple_convertible<_Tuple, pair>::value;
|
||||
}
|
||||
|
||||
template <class _Tuple>
|
||||
static constexpr bool __enable_assign() {
|
||||
return __tuple_assignable<_Tuple, pair>::value;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Tuple>
|
||||
using _CheckTLC = typename conditional<
|
||||
__tuple_like_with_size<_Tuple, 2>::value
|
||||
&& !is_same<typename decay<_Tuple>::type, pair>::value,
|
||||
_CheckTupleLikeConstructor,
|
||||
__check_tuple_constructor_fail
|
||||
>::type;
|
||||
|
||||
template<bool _Dummy = true, _EnableB<
|
||||
_CheckArgsDep<_Dummy>::template __enable_default<_T1, _T2>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
pair() : first(), second() {}
|
||||
|
||||
template <bool _Dummy = true, _EnableB<
|
||||
_CheckArgsDep<_Dummy>::template __enable_explicit<_T1 const&, _T2 const&>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
explicit pair(_T1 const& __t1, _T2 const& __t2)
|
||||
: first(__t1), second(__t2) {}
|
||||
|
||||
template<bool _Dummy = true, _EnableB<
|
||||
_CheckArgsDep<_Dummy>::template __enable_implicit<_T1 const&, _T2 const&>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(_T1 const& __t1, _T2 const& __t2)
|
||||
: first(__t1), second(__t2) {}
|
||||
|
||||
template<class _U1, class _U2, _EnableB<
|
||||
_CheckArgs::template __enable_explicit<_U1, _U2>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
explicit pair(_U1&& __u1, _U2&& __u2)
|
||||
: first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {}
|
||||
|
||||
template<class _U1, class _U2, _EnableB<
|
||||
_CheckArgs::template __enable_implicit<_U1, _U2>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(_U1&& __u1, _U2&& __u2)
|
||||
: first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {}
|
||||
|
||||
template<class _U1, class _U2, _EnableB<
|
||||
_CheckArgs::template __enable_explicit<_U1 const&, _U2 const&>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
explicit pair(pair<_U1, _U2> const& __p)
|
||||
: first(__p.first), second(__p.second) {}
|
||||
|
||||
template<class _U1, class _U2, _EnableB<
|
||||
_CheckArgs::template __enable_implicit<_U1 const&, _U2 const&>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(pair<_U1, _U2> const& __p)
|
||||
: first(__p.first), second(__p.second) {}
|
||||
|
||||
template<class _U1, class _U2, _EnableB<
|
||||
_CheckArgs::template __enable_explicit<_U1, _U2>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
explicit pair(pair<_U1, _U2>&&__p)
|
||||
: first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {}
|
||||
|
||||
template<class _U1, class _U2, _EnableB<
|
||||
_CheckArgs::template __enable_implicit<_U1, _U2>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(pair<_U1, _U2>&& __p)
|
||||
: first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {}
|
||||
|
||||
template<class _Tuple, _EnableB<
|
||||
_CheckTLC<_Tuple>::template __enable_explicit<_Tuple>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
explicit pair(_Tuple&& __p)
|
||||
: first(_VSTD::get<0>(_VSTD::forward<_Tuple>(__p))),
|
||||
second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {}
|
||||
|
||||
template<class _Tuple, _EnableB<
|
||||
_CheckTLC<_Tuple>::template __enable_implicit<_Tuple>()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(_Tuple&& __p)
|
||||
: first(_VSTD::get<0>(_VSTD::forward<_Tuple>(__p))),
|
||||
second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {}
|
||||
|
||||
template <class... _Args1, class... _Args2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair(piecewise_construct_t __pc,
|
||||
tuple<_Args1...> __first_args, tuple<_Args2...> __second_args)
|
||||
: pair(__pc, __first_args, __second_args,
|
||||
typename __make_tuple_indices<sizeof...(_Args1)>::type(),
|
||||
typename __make_tuple_indices<sizeof...(_Args2) >::type()) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair& operator=(typename conditional<
|
||||
is_copy_assignable<first_type>::value &&
|
||||
is_copy_assignable<second_type>::value,
|
||||
pair, __nat>::type const& __p)
|
||||
_NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value &&
|
||||
is_nothrow_copy_assignable<second_type>::value)
|
||||
{
|
||||
|
@ -373,9 +501,11 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
|
|||
return *this;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair& operator=(_MoveAssignT&& __p)
|
||||
pair& operator=(typename conditional<
|
||||
is_move_assignable<first_type>::value &&
|
||||
is_move_assignable<second_type>::value,
|
||||
pair, __nat>::type&& __p)
|
||||
_NOEXCEPT_(is_nothrow_move_assignable<first_type>::value &&
|
||||
is_nothrow_move_assignable<second_type>::value)
|
||||
{
|
||||
|
@ -383,68 +513,18 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
|
|||
second = _VSTD::forward<second_type>(__p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _Tuple, _EnableB<
|
||||
_CheckTLC<_Tuple>::template __enable_assign()
|
||||
> = false>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair& operator=(_Tuple&& __p) {
|
||||
first = _VSTD::get<0>(_VSTD::forward<_Tuple>(__p));
|
||||
second = _VSTD::get<1>(_VSTD::forward<_Tuple>(__p));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
|
||||
template <class _U1, class _U2,
|
||||
class = typename enable_if<is_convertible<_U1, first_type>::value &&
|
||||
is_convertible<_U2, second_type>::value>::type>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(_U1&& __u1, _U2&& __u2)
|
||||
: first(_VSTD::forward<_U1>(__u1)),
|
||||
second(_VSTD::forward<_U2>(__u2))
|
||||
{}
|
||||
|
||||
template<class _U1, class _U2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(pair<_U1, _U2>&& __p,
|
||||
typename enable_if<is_convertible<_U1, _T1>::value &&
|
||||
is_convertible<_U2, _T2>::value>::type* = 0)
|
||||
: first(_VSTD::forward<_U1>(__p.first)),
|
||||
second(_VSTD::forward<_U2>(__p.second)) {}
|
||||
|
||||
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
template<class _Tuple,
|
||||
class = typename enable_if<__tuple_convertible<_Tuple, pair>::value>::type>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
pair(_Tuple&& __p)
|
||||
: first(_VSTD::forward<typename tuple_element<0,
|
||||
typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<0>(__p))),
|
||||
second(_VSTD::forward<typename tuple_element<1,
|
||||
typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<1>(__p)))
|
||||
{}
|
||||
|
||||
|
||||
|
||||
template <class... _Args1, class... _Args2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args,
|
||||
tuple<_Args2...> __second_args)
|
||||
: pair(__pc, __first_args, __second_args,
|
||||
typename __make_tuple_indices<sizeof...(_Args1)>::type(),
|
||||
typename __make_tuple_indices<sizeof...(_Args2) >::type())
|
||||
{}
|
||||
|
||||
template <class _Tuple,
|
||||
class = typename enable_if<!is_same<typename decay<_Tuple>::type, pair>::value && __tuple_assignable<_Tuple, pair>::value>::type>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair&
|
||||
operator=(_Tuple&& __p)
|
||||
{
|
||||
typedef typename __make_tuple_types<_Tuple>::type _TupleRef;
|
||||
typedef typename tuple_element<0, _TupleRef>::type _U0;
|
||||
typedef typename tuple_element<1, _TupleRef>::type _U1;
|
||||
first = _VSTD::forward<_U0>(_VSTD::get<0>(__p));
|
||||
second = _VSTD::forward<_U1>(_VSTD::get<1>(__p));
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable<first_type>::value &&
|
||||
|
@ -456,13 +536,13 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
|
|||
}
|
||||
private:
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair(piecewise_construct_t,
|
||||
tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
|
||||
__tuple_indices<_I1...>, __tuple_indices<_I2...>);
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
|
|
|
@ -7,24 +7,93 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <utility>
|
||||
|
||||
// template <class T1, class T2> struct pair
|
||||
|
||||
// template<class U, class V> pair(U&& x, V&& y);
|
||||
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
#include "archetypes.hpp"
|
||||
#include "test_convertible.hpp"
|
||||
|
||||
template <class T1, class T1Arg,
|
||||
bool CanCopy = true, bool CanConvert = CanCopy>
|
||||
void test_sfinae() {
|
||||
using P1 = std::pair<T1, int>;
|
||||
using P2 = std::pair<int, T1>;
|
||||
using T2 = int const&;
|
||||
static_assert(std::is_constructible<P1, T1Arg, T2>::value == CanCopy, "");
|
||||
static_assert(test_convertible<P1, T1Arg, T2>() == CanConvert, "");
|
||||
static_assert(std::is_constructible<P2, T2, T1Arg>::value == CanCopy, "");
|
||||
static_assert(test_convertible<P2, T2, T1Arg>() == CanConvert, "");
|
||||
}
|
||||
|
||||
struct ExplicitT {
|
||||
constexpr explicit ExplicitT(int x) : value(x) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
struct ImplicitT {
|
||||
constexpr ImplicitT(int x) : value(x) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
{
|
||||
typedef std::pair<std::unique_ptr<int>, short*> P;
|
||||
P p(std::unique_ptr<int>(new int(3)), nullptr);
|
||||
assert(*p.first == 3);
|
||||
assert(p.second == nullptr);
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
{
|
||||
// Test non-const lvalue and rvalue types
|
||||
test_sfinae<AllCtors, AllCtors&>();
|
||||
test_sfinae<AllCtors, AllCtors&&>();
|
||||
test_sfinae<ExplicitAllCtors, ExplicitAllCtors&, true, false>();
|
||||
test_sfinae<ExplicitAllCtors, ExplicitAllCtors&&, true, false>();
|
||||
test_sfinae<CopyOnly, CopyOnly&>();
|
||||
test_sfinae<CopyOnly, CopyOnly&&>();
|
||||
test_sfinae<ExplicitCopyOnly, ExplicitCopyOnly&, true, false>();
|
||||
test_sfinae<ExplicitCopyOnly, ExplicitCopyOnly&&, true, false>();
|
||||
test_sfinae<MoveOnly, MoveOnly&, false>();
|
||||
test_sfinae<MoveOnly, MoveOnly&&>();
|
||||
test_sfinae<ExplicitMoveOnly, ExplicitMoveOnly&, false>();
|
||||
test_sfinae<ExplicitMoveOnly, ExplicitMoveOnly&&, true, false>();
|
||||
test_sfinae<NonCopyable, NonCopyable&, false>();
|
||||
test_sfinae<NonCopyable, NonCopyable&&, false>();
|
||||
test_sfinae<ExplicitNonCopyable, ExplicitNonCopyable&, false>();
|
||||
test_sfinae<ExplicitNonCopyable, ExplicitNonCopyable&&, false>();
|
||||
}
|
||||
{
|
||||
// Test converting types
|
||||
test_sfinae<ConvertingType, int&>();
|
||||
test_sfinae<ConvertingType, const int&>();
|
||||
test_sfinae<ConvertingType, int&&>();
|
||||
test_sfinae<ConvertingType, const int&&>();
|
||||
test_sfinae<ExplicitConvertingType, int&, true, false>();
|
||||
test_sfinae<ExplicitConvertingType, const int&, true, false>();
|
||||
test_sfinae<ExplicitConvertingType, int&&, true, false>();
|
||||
test_sfinae<ExplicitConvertingType, const int&&, true, false>();
|
||||
}
|
||||
#if TEST_STD_VER > 11
|
||||
{ // explicit constexpr test
|
||||
constexpr std::pair<ExplicitT, ExplicitT> p(42, 43);
|
||||
static_assert(p.first.value == 42, "");
|
||||
static_assert(p.second.value == 43, "");
|
||||
}
|
||||
{ // implicit constexpr test
|
||||
constexpr std::pair<ImplicitT, ImplicitT> p = {42, 43};
|
||||
static_assert(p.first.value == 42, "");
|
||||
static_assert(p.second.value == 43, "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <utility>
|
||||
|
||||
// template <class T1, class T2> struct pair
|
||||
|
@ -16,25 +18,33 @@
|
|||
#include <utility>
|
||||
#include <cassert>
|
||||
|
||||
class A
|
||||
{
|
||||
int data_;
|
||||
public:
|
||||
A(int data) : data_(data) {}
|
||||
#include "archetypes.hpp"
|
||||
#include "test_convertible.hpp"
|
||||
|
||||
bool operator==(const A& a) const {return data_ == a.data_;}
|
||||
struct ExplicitT {
|
||||
constexpr explicit ExplicitT(int x) : value(x) {}
|
||||
constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
class AC
|
||||
{
|
||||
int data_;
|
||||
public:
|
||||
constexpr AC(int data) : data_(data) {}
|
||||
|
||||
constexpr bool operator==(const AC& a) const {return data_ == a.data_;}
|
||||
struct ImplicitT {
|
||||
constexpr ImplicitT(int x) : value(x) {}
|
||||
constexpr ImplicitT(ImplicitT const& o) : value(o.value) {}
|
||||
int value;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class T1,
|
||||
bool CanCopy = true, bool CanConvert = CanCopy>
|
||||
void test_sfinae() {
|
||||
using P1 = std::pair<T1, int>;
|
||||
using P2 = std::pair<int, T1>;
|
||||
using T1Arg = T1 const&;
|
||||
using T2 = int const&;
|
||||
static_assert(std::is_constructible<P1, T1Arg, T2>::value == CanCopy, "");
|
||||
static_assert(test_convertible<P1, T1Arg, T2>() == CanConvert, "");
|
||||
static_assert(std::is_constructible<P2, T2, T1Arg>::value == CanCopy, "");
|
||||
static_assert(test_convertible<P2, T2, T1Arg>() == CanConvert, "");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
@ -45,13 +55,22 @@ int main()
|
|||
assert(p.second == nullptr);
|
||||
}
|
||||
{
|
||||
typedef std::pair<A, int> P;
|
||||
typedef std::pair<ImplicitT, int> P;
|
||||
P p(1, 2);
|
||||
assert(p.first == A(1));
|
||||
assert(p.first.value == 1);
|
||||
assert(p.second == 2);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
{
|
||||
test_sfinae<AllCtors>();
|
||||
test_sfinae<ExplicitAllCtors, true, false>();
|
||||
test_sfinae<CopyOnly>();
|
||||
test_sfinae<ExplicitCopyOnly, true, false>();
|
||||
test_sfinae<MoveOnly, false>();
|
||||
test_sfinae<ExplicitMoveOnly, false>();
|
||||
test_sfinae<NonCopyable, false>();
|
||||
test_sfinae<ExplicitNonCopyable, false>();
|
||||
}
|
||||
#if TEST_STD_VER > 11
|
||||
{
|
||||
typedef std::pair<float, short*> P;
|
||||
constexpr P p(3.5f, 0);
|
||||
|
@ -59,10 +78,20 @@ int main()
|
|||
static_assert(p.second == nullptr, "");
|
||||
}
|
||||
{
|
||||
typedef std::pair<AC, int> P;
|
||||
constexpr P p(1, 2);
|
||||
static_assert(p.first == AC(1), "");
|
||||
static_assert(p.second == 2, "");
|
||||
using P = std::pair<ExplicitT, int>;
|
||||
constexpr ExplicitT e(42);
|
||||
constexpr int x = 10;
|
||||
constexpr P p(e, x);
|
||||
static_assert(p.first.value == 42, "");
|
||||
static_assert(p.second == 10, "");
|
||||
}
|
||||
{
|
||||
using P = std::pair<ImplicitT, int>;
|
||||
constexpr ImplicitT e(42);
|
||||
constexpr int x = 10;
|
||||
constexpr P p = {e, x};
|
||||
static_assert(p.first.value == 42, "");
|
||||
static_assert(p.second == 10, "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <utility>
|
||||
|
||||
// template <class T1, class T2> struct pair
|
||||
|
||||
// pair(const T1& x, const T2& y);
|
||||
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
|
||||
class A
|
||||
{
|
||||
int data_;
|
||||
public:
|
||||
A(int data) : data_(data) {}
|
||||
|
||||
bool operator==(const A& a) const {return data_ == a.data_;}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
typedef std::pair<float, short*> P;
|
||||
P p(3.5f, 0);
|
||||
assert(p.first == 3.5f);
|
||||
assert(p.second == nullptr);
|
||||
}
|
||||
{
|
||||
typedef std::pair<A, int> P;
|
||||
P p(1, 2);
|
||||
assert(p.first == A(1));
|
||||
assert(p.second == 2);
|
||||
}
|
||||
}
|
|
@ -7,27 +7,151 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <utility>
|
||||
|
||||
// template <class T1, class T2> struct pair
|
||||
|
||||
// template <class U, class V> pair(const pair<U, V>& p);
|
||||
// template <class U, class V> EXPLICIT constexpr pair(const pair<U, V>& p);
|
||||
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
|
||||
#include "archetypes.hpp"
|
||||
#include "test_convertible.hpp"
|
||||
|
||||
template <class T1, class U1,
|
||||
bool CanCopy = true, bool CanConvert = CanCopy>
|
||||
void test_pair_const()
|
||||
{
|
||||
using P1 = std::pair<T1, int>;
|
||||
using P2 = std::pair<int, T1>;
|
||||
using UP1 = std::pair<U1, int> const&;
|
||||
using UP2 = std::pair<int, U1> const&;
|
||||
static_assert(std::is_constructible<P1, UP1>::value == CanCopy, "");
|
||||
static_assert(test_convertible<P1, UP1>() == CanConvert, "");
|
||||
static_assert(std::is_constructible<P2, UP2>::value == CanCopy, "");
|
||||
static_assert(test_convertible<P2, UP2>() == CanConvert, "");
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
struct DPair : public std::pair<T, U> {
|
||||
using Base = std::pair<T, U>;
|
||||
using Base::Base;
|
||||
};
|
||||
|
||||
struct ExplicitT {
|
||||
constexpr explicit ExplicitT(int x) : value(x) {}
|
||||
constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
struct ImplicitT {
|
||||
constexpr ImplicitT(int x) : value(x) {}
|
||||
constexpr ImplicitT(ImplicitT const& o) : value(o.value) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
typedef std::pair<int, short> P1;
|
||||
typedef std::pair<double, long> P2;
|
||||
P1 p1(3, 4);
|
||||
P2 p2 = p1;
|
||||
const P1 p1(3, 4);
|
||||
const P2 p2 = p1;
|
||||
assert(p2.first == 3);
|
||||
assert(p2.second == 4);
|
||||
}
|
||||
{
|
||||
// We allow derived types to use this constructor
|
||||
using P1 = DPair<long, long>;
|
||||
using P2 = std::pair<int, int>;
|
||||
P1 p1(42, 101);
|
||||
P2 p2(p1);
|
||||
assert(p2.first == 42);
|
||||
assert(p2.second = 101);
|
||||
}
|
||||
{
|
||||
test_pair_const<AllCtors, AllCtors>(); // copy construction
|
||||
test_pair_const<AllCtors, AllCtors&>();
|
||||
test_pair_const<AllCtors, AllCtors&&>();
|
||||
test_pair_const<AllCtors, const AllCtors&>();
|
||||
test_pair_const<AllCtors, const AllCtors&&>();
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
test_pair_const<ExplicitAllCtors, ExplicitAllCtors>(); // copy construction
|
||||
test_pair_const<ExplicitAllCtors, ExplicitAllCtors&, true, false>();
|
||||
test_pair_const<ExplicitAllCtors, ExplicitAllCtors&&, true, false>();
|
||||
test_pair_const<ExplicitAllCtors, const ExplicitAllCtors&, true, false>();
|
||||
test_pair_const<ExplicitAllCtors, const ExplicitAllCtors&&, true, false>();
|
||||
|
||||
test_pair_const<MoveOnly, MoveOnly, false>(); // copy construction
|
||||
test_pair_const<MoveOnly, MoveOnly&, false>();
|
||||
test_pair_const<MoveOnly, MoveOnly&&, false>();
|
||||
|
||||
test_pair_const<ExplicitMoveOnly, ExplicitMoveOnly, false>(); // copy construction
|
||||
test_pair_const<ExplicitMoveOnly, ExplicitMoveOnly&, false>();
|
||||
test_pair_const<ExplicitMoveOnly, ExplicitMoveOnly&&, false>();
|
||||
|
||||
test_pair_const<CopyOnly, CopyOnly>();
|
||||
test_pair_const<CopyOnly, CopyOnly&>();
|
||||
test_pair_const<CopyOnly, CopyOnly&&>();
|
||||
|
||||
test_pair_const<ExplicitCopyOnly, ExplicitCopyOnly>();
|
||||
test_pair_const<ExplicitCopyOnly, ExplicitCopyOnly&, true, false>();
|
||||
test_pair_const<ExplicitCopyOnly, ExplicitCopyOnly&&, true, false>();
|
||||
|
||||
test_pair_const<NonCopyable, NonCopyable, false>();
|
||||
test_pair_const<NonCopyable, NonCopyable&, false>();
|
||||
test_pair_const<NonCopyable, NonCopyable&&, false>();
|
||||
test_pair_const<NonCopyable, const NonCopyable&, false>();
|
||||
test_pair_const<NonCopyable, const NonCopyable&&, false>();
|
||||
}
|
||||
|
||||
{ // Test construction of references
|
||||
test_pair_const<NonCopyable&, NonCopyable&>();
|
||||
test_pair_const<NonCopyable&, NonCopyable&&>();
|
||||
test_pair_const<NonCopyable&, NonCopyable const&, false>();
|
||||
test_pair_const<NonCopyable const&, NonCopyable&&>();
|
||||
test_pair_const<NonCopyable&&, NonCopyable&&, false>();
|
||||
|
||||
test_pair_const<ConvertingType&, int, false>();
|
||||
test_pair_const<ExplicitConvertingType&, int, false>();
|
||||
// Unfortunately the below conversions are allowed and create dangling
|
||||
// references.
|
||||
//test_pair_const<ConvertingType&&, int>();
|
||||
//test_pair_const<ConvertingType const&, int>();
|
||||
//test_pair_const<ConvertingType const&&, int>();
|
||||
// But these are not because the converting constructor is explicit.
|
||||
test_pair_const<ExplicitConvertingType&&, int, false>();
|
||||
test_pair_const<ExplicitConvertingType const&, int, false>();
|
||||
test_pair_const<ExplicitConvertingType const&&, int, false>();
|
||||
|
||||
}
|
||||
{
|
||||
test_pair_const<AllCtors, int, false>();
|
||||
test_pair_const<ExplicitAllCtors, int, false>();
|
||||
test_pair_const<ConvertingType, int>();
|
||||
test_pair_const<ExplicitConvertingType, int, true, false>();
|
||||
|
||||
test_pair_const<ConvertingType, int>();
|
||||
test_pair_const<ConvertingType, ConvertingType>();
|
||||
test_pair_const<ConvertingType, ConvertingType const&>();
|
||||
test_pair_const<ConvertingType, ConvertingType&>();
|
||||
test_pair_const<ConvertingType, ConvertingType&&>();
|
||||
|
||||
test_pair_const<ExplicitConvertingType, int, true, false>();
|
||||
test_pair_const<ExplicitConvertingType, int&, true, false>();
|
||||
test_pair_const<ExplicitConvertingType, const int&, true, false>();
|
||||
test_pair_const<ExplicitConvertingType, int&&, true, false>();
|
||||
test_pair_const<ExplicitConvertingType, const int&&, true, false>();
|
||||
|
||||
test_pair_const<ExplicitConvertingType, ExplicitConvertingType>();
|
||||
test_pair_const<ExplicitConvertingType, ExplicitConvertingType const&, true, false>();
|
||||
test_pair_const<ExplicitConvertingType, ExplicitConvertingType&, true, false>();
|
||||
test_pair_const<ExplicitConvertingType, ExplicitConvertingType&&, true, false>();
|
||||
}
|
||||
#if TEST_STD_VER > 11
|
||||
{
|
||||
typedef std::pair<int, short> P1;
|
||||
typedef std::pair<double, long> P2;
|
||||
|
@ -36,5 +160,21 @@ int main()
|
|||
static_assert(p2.first == 3, "");
|
||||
static_assert(p2.second == 4, "");
|
||||
}
|
||||
{
|
||||
using P1 = std::pair<int, int>;
|
||||
using P2 = std::pair<ExplicitT, ExplicitT>;
|
||||
constexpr P1 p1(42, 101);
|
||||
constexpr P2 p2(p1);
|
||||
static_assert(p2.first.value == 42, "");
|
||||
static_assert(p2.second.value == 101, "");
|
||||
}
|
||||
{
|
||||
using P1 = std::pair<int, int>;
|
||||
using P2 = std::pair<ImplicitT, ImplicitT>;
|
||||
constexpr P1 p1(42, 101);
|
||||
constexpr P2 p2 = p1;
|
||||
static_assert(p2.first.value == 42, "");
|
||||
static_assert(p2.second.value == 101, "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <utility>
|
||||
|
||||
// template <class T1, class T2> struct pair
|
||||
|
||||
// template <class U, class V> pair(const pair<U, V>& p);
|
||||
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
typedef std::pair<int, short> P1;
|
||||
typedef std::pair<double, long> P2;
|
||||
const P1 p1(3, 4);
|
||||
const P2 p2 = p1;
|
||||
assert(p2.first == 3);
|
||||
assert(p2.second == 4);
|
||||
}
|
||||
}
|
|
@ -27,14 +27,15 @@
|
|||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
typedef std::pair<float, short*> P;
|
||||
P p;
|
||||
assert(p.first == 0.0f);
|
||||
assert(p.second == nullptr);
|
||||
typedef std::pair<float, short*> P;
|
||||
P p;
|
||||
assert(p.first == 0.0f);
|
||||
assert(p.second == nullptr);
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
|
@ -43,5 +44,11 @@ int main()
|
|||
static_assert(p.first == 0.0f, "");
|
||||
static_assert(p.second == nullptr, "");
|
||||
}
|
||||
{
|
||||
using P = std::pair<int, NoDefault>;
|
||||
static_assert(!std::is_default_constructible<P>::value, "");
|
||||
using P2 = std::pair<NoDefault, int>;
|
||||
static_assert(!std::is_default_constructible<P>::value, "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: c++11
|
||||
|
||||
// <utility>
|
||||
|
||||
// Test that only the default constructor is constexpr in C++11
|
||||
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
|
||||
struct ExplicitT {
|
||||
constexpr explicit ExplicitT(int x) : value(x) {}
|
||||
constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
struct ImplicitT {
|
||||
constexpr ImplicitT(int x) : value(x) {}
|
||||
constexpr ImplicitT(ImplicitT const& o) : value(o.value) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using P = std::pair<int, int>;
|
||||
constexpr int x = 42;
|
||||
constexpr P default_p{};
|
||||
constexpr P copy_p(default_p);
|
||||
constexpr P const_U_V(x, x); // expected-error {{must be initialized by a constant expression}}
|
||||
constexpr P U_V(42, 101); // expected-error {{must be initialized by a constant expression}}
|
||||
}
|
||||
{
|
||||
using P = std::pair<ExplicitT, ExplicitT>;
|
||||
constexpr std::pair<int, int> other;
|
||||
constexpr ExplicitT e(99);
|
||||
constexpr P const_U_V(e, e); // expected-error {{must be initialized by a constant expression}}
|
||||
constexpr P U_V(42, 101); // expected-error {{must be initialized by a constant expression}}
|
||||
constexpr P pair_U_V(other); // expected-error {{must be initialized by a constant expression}}
|
||||
}
|
||||
{
|
||||
using P = std::pair<ImplicitT, ImplicitT>;
|
||||
constexpr std::pair<int, int> other;
|
||||
constexpr ImplicitT i = 99;
|
||||
constexpr P const_U_V = {i, i}; // expected-error {{must be initialized by a constant expression}}
|
||||
constexpr P U_V = {42, 101}; // expected-error {{must be initialized by a constant expression}}
|
||||
constexpr P pair_U_V = other; // expected-error {{must be initialized by a constant expression}}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <utility>
|
||||
|
||||
// template <class T1, class T2> struct pair
|
||||
|
@ -17,6 +19,23 @@
|
|||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
#include "archetypes.hpp"
|
||||
#include "test_convertible.hpp"
|
||||
|
||||
template <class T1, class U1,
|
||||
bool CanCopy = true, bool CanConvert = CanCopy>
|
||||
void test_pair_rv()
|
||||
{
|
||||
using P1 = std::pair<T1, int>;
|
||||
using P2 = std::pair<int, T1>;
|
||||
using UP1 = std::pair<U1, int>&&;
|
||||
using UP2 = std::pair<int, U1>&&;
|
||||
static_assert(std::is_constructible<P1, UP1>::value == CanCopy, "");
|
||||
static_assert(test_convertible<P1, UP1>() == CanConvert, "");
|
||||
static_assert(std::is_constructible<P2, UP2>::value == CanCopy, "");
|
||||
static_assert(test_convertible<P2, UP2>() == CanConvert, "");
|
||||
}
|
||||
|
||||
struct Base
|
||||
{
|
||||
virtual ~Base() {}
|
||||
|
@ -27,9 +46,25 @@ struct Derived
|
|||
{
|
||||
};
|
||||
|
||||
|
||||
template <class T, class U>
|
||||
struct DPair : public std::pair<T, U> {
|
||||
using Base = std::pair<T, U>;
|
||||
using Base::Base;
|
||||
};
|
||||
|
||||
struct ExplicitT {
|
||||
constexpr explicit ExplicitT(int x) : value(x) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
struct ImplicitT {
|
||||
constexpr ImplicitT(int x) : value(x) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
{
|
||||
typedef std::pair<std::unique_ptr<Derived>, short> P1;
|
||||
typedef std::pair<std::unique_ptr<Base>, long> P2;
|
||||
|
@ -38,5 +73,104 @@ int main()
|
|||
assert(p2.first == nullptr);
|
||||
assert(p2.second == 4);
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
{
|
||||
// We allow derived types to use this constructor
|
||||
using P1 = DPair<long, long>;
|
||||
using P2 = std::pair<int, int>;
|
||||
P1 p1(42, 101);
|
||||
P2 p2(std::move(p1));
|
||||
assert(p2.first == 42);
|
||||
assert(p2.second = 101);
|
||||
}
|
||||
{
|
||||
test_pair_rv<AllCtors, AllCtors>();
|
||||
test_pair_rv<AllCtors, AllCtors&>();
|
||||
test_pair_rv<AllCtors, AllCtors&&>();
|
||||
test_pair_rv<AllCtors, const AllCtors&>();
|
||||
test_pair_rv<AllCtors, const AllCtors&&>();
|
||||
|
||||
test_pair_rv<ExplicitAllCtors, ExplicitAllCtors>();
|
||||
test_pair_rv<ExplicitAllCtors, ExplicitAllCtors&, true, false>();
|
||||
test_pair_rv<ExplicitAllCtors, ExplicitAllCtors&&, true, false>();
|
||||
test_pair_rv<ExplicitAllCtors, const ExplicitAllCtors&, true, false>();
|
||||
test_pair_rv<ExplicitAllCtors, const ExplicitAllCtors&&, true, false>();
|
||||
|
||||
test_pair_rv<MoveOnly, MoveOnly>();
|
||||
test_pair_rv<MoveOnly, MoveOnly&, false>();
|
||||
test_pair_rv<MoveOnly, MoveOnly&&>();
|
||||
|
||||
test_pair_rv<ExplicitMoveOnly, ExplicitMoveOnly>(); // copy construction
|
||||
test_pair_rv<ExplicitMoveOnly, ExplicitMoveOnly&, false>();
|
||||
test_pair_rv<ExplicitMoveOnly, ExplicitMoveOnly&&, true, false>();
|
||||
|
||||
test_pair_rv<CopyOnly, CopyOnly>();
|
||||
test_pair_rv<CopyOnly, CopyOnly&>();
|
||||
test_pair_rv<CopyOnly, CopyOnly&&>();
|
||||
|
||||
test_pair_rv<ExplicitCopyOnly, ExplicitCopyOnly>();
|
||||
test_pair_rv<ExplicitCopyOnly, ExplicitCopyOnly&, true, false>();
|
||||
test_pair_rv<ExplicitCopyOnly, ExplicitCopyOnly&&, true, false>();
|
||||
|
||||
test_pair_rv<NonCopyable, NonCopyable, false>();
|
||||
test_pair_rv<NonCopyable, NonCopyable&, false>();
|
||||
test_pair_rv<NonCopyable, NonCopyable&&, false>();
|
||||
test_pair_rv<NonCopyable, const NonCopyable&, false>();
|
||||
test_pair_rv<NonCopyable, const NonCopyable&&, false>();
|
||||
}
|
||||
{ // Test construction of references
|
||||
test_pair_rv<NonCopyable&, NonCopyable&>();
|
||||
test_pair_rv<NonCopyable&, NonCopyable&&>();
|
||||
test_pair_rv<NonCopyable&, NonCopyable const&, false>();
|
||||
test_pair_rv<NonCopyable const&, NonCopyable&&>();
|
||||
test_pair_rv<NonCopyable&&, NonCopyable&&>();
|
||||
|
||||
test_pair_rv<ConvertingType&, int, false>();
|
||||
test_pair_rv<ExplicitConvertingType&, int, false>();
|
||||
// Unfortunately the below conversions are allowed and create dangling
|
||||
// references.
|
||||
//test_pair_rv<ConvertingType&&, int>();
|
||||
//test_pair_rv<ConvertingType const&, int>();
|
||||
//test_pair_rv<ConvertingType const&&, int>();
|
||||
// But these are not because the converting constructor is explicit.
|
||||
test_pair_rv<ExplicitConvertingType&&, int, false>();
|
||||
test_pair_rv<ExplicitConvertingType const&, int, false>();
|
||||
test_pair_rv<ExplicitConvertingType const&&, int, false>();
|
||||
}
|
||||
{
|
||||
test_pair_rv<AllCtors, int, false>();
|
||||
test_pair_rv<ExplicitAllCtors, int, false>();
|
||||
test_pair_rv<ConvertingType, int>();
|
||||
test_pair_rv<ExplicitConvertingType, int, true, false>();
|
||||
|
||||
test_pair_rv<ConvertingType, int>();
|
||||
test_pair_rv<ConvertingType, ConvertingType>();
|
||||
test_pair_rv<ConvertingType, ConvertingType const&>();
|
||||
test_pair_rv<ConvertingType, ConvertingType&>();
|
||||
test_pair_rv<ConvertingType, ConvertingType&&>();
|
||||
|
||||
test_pair_rv<ExplicitConvertingType, int, true, false>();
|
||||
test_pair_rv<ExplicitConvertingType, int&, true, false>();
|
||||
test_pair_rv<ExplicitConvertingType, const int&, true, false>();
|
||||
test_pair_rv<ExplicitConvertingType, int&&, true, false>();
|
||||
test_pair_rv<ExplicitConvertingType, const int&&, true, false>();
|
||||
|
||||
test_pair_rv<ExplicitConvertingType, ExplicitConvertingType>();
|
||||
test_pair_rv<ExplicitConvertingType, ExplicitConvertingType const&, true, false>();
|
||||
test_pair_rv<ExplicitConvertingType, ExplicitConvertingType&, true, false>();
|
||||
test_pair_rv<ExplicitConvertingType, ExplicitConvertingType&&, true, false>();
|
||||
}
|
||||
#if TEST_STD_VER > 11
|
||||
{ // explicit constexpr test
|
||||
constexpr std::pair<int, int> p1(42, 43);
|
||||
constexpr std::pair<ExplicitT, ExplicitT> p2(std::move(p1));
|
||||
static_assert(p2.first.value == 42, "");
|
||||
static_assert(p2.second.value == 43, "");
|
||||
}
|
||||
{ // implicit constexpr test
|
||||
constexpr std::pair<int, int> p1(42, 43);
|
||||
constexpr std::pair<ImplicitT, ImplicitT> p2 = std::move(p1);
|
||||
static_assert(p2.first.value == 42, "");
|
||||
static_assert(p2.second.value == 43, "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// template <class T, class U> struct pair;
|
||||
|
||||
// pair(pair const&) = default;
|
||||
// pair(pair &&) = default;
|
||||
// pair& operator=(pair const&);
|
||||
// pair& operator=(pair&&);
|
||||
|
||||
// Test that the copy/move constructors and assignment operators are
|
||||
// correctly defined or deleted based on the properties of `T` and `U`.
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "archetypes.hpp"
|
||||
|
||||
namespace ConstructorTest {
|
||||
|
||||
template <class T1, bool CanCopy = true, bool CanMove = CanCopy> void test() {
|
||||
using P1 = std::pair<T1, int>;
|
||||
using P2 = std::pair<int, T1>;
|
||||
static_assert(std::is_copy_constructible<P1>::value == CanCopy);
|
||||
static_assert(std::is_move_constructible<P1>::value == CanMove);
|
||||
static_assert(std::is_copy_constructible<P2>::value == CanCopy);
|
||||
static_assert(std::is_move_constructible<P2>::value == CanMove);
|
||||
};
|
||||
|
||||
} // namespace ConstructorTest
|
||||
|
||||
void test_constructors_exist() {
|
||||
using namespace ConstructorTest;
|
||||
{
|
||||
test<int>();
|
||||
test<int &>();
|
||||
test<int &&, false, true>();
|
||||
test<const int>();
|
||||
test<const int &>();
|
||||
test<const int &&, false, true>();
|
||||
}
|
||||
{
|
||||
test<Copyable>();
|
||||
test<Copyable &>();
|
||||
test<Copyable &&, false, true>();
|
||||
}
|
||||
{
|
||||
test<NonCopyable, false>();
|
||||
test<NonCopyable &, true>();
|
||||
test<NonCopyable &&, false, true>();
|
||||
}
|
||||
{
|
||||
// Even though CopyOnly has an explicitly deleted move constructor
|
||||
// pair's move constructor is only implicitly deleted and therefore
|
||||
// it doesn't participate in overload resolution.
|
||||
test<CopyOnly, true, true>();
|
||||
test<CopyOnly &, true>();
|
||||
test<CopyOnly &&, false, true>();
|
||||
}
|
||||
{
|
||||
test<MoveOnly, false, true>();
|
||||
test<MoveOnly &, true>();
|
||||
test<MoveOnly &&, false, true>();
|
||||
}
|
||||
}
|
||||
|
||||
namespace AssignmentOperatorTest {
|
||||
|
||||
template <class T1, bool CanCopy = true, bool CanMove = CanCopy> void test() {
|
||||
using P1 = std::pair<T1, int>;
|
||||
using P2 = std::pair<int, T1>;
|
||||
static_assert(std::is_copy_assignable<P1>::value == CanCopy);
|
||||
static_assert(std::is_move_assignable<P1>::value == CanMove);
|
||||
static_assert(std::is_copy_assignable<P2>::value == CanCopy);
|
||||
static_assert(std::is_move_assignable<P2>::value == CanMove);
|
||||
};
|
||||
|
||||
} // namespace AssignmentOperatorTest
|
||||
|
||||
void test_assignment_operator_exists() {
|
||||
using namespace AssignmentOperatorTest;
|
||||
{
|
||||
test<int>();
|
||||
test<int &>();
|
||||
test<int &&>();
|
||||
test<const int, false>();
|
||||
test<const int &, false>();
|
||||
test<const int &&, false>();
|
||||
}
|
||||
{
|
||||
test<Copyable>();
|
||||
test<Copyable &>();
|
||||
test<Copyable &&>();
|
||||
}
|
||||
{
|
||||
test<NonCopyable, false>();
|
||||
test<NonCopyable &, false>();
|
||||
test<NonCopyable &&, false>();
|
||||
}
|
||||
{
|
||||
test<CopyOnly, true>();
|
||||
test<CopyOnly &, true>();
|
||||
test<CopyOnly &&, true>();
|
||||
}
|
||||
{
|
||||
test<MoveOnly, false, true>();
|
||||
test<MoveOnly &, false, false>();
|
||||
test<MoveOnly &&, false, true>();
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_constructors_exist();
|
||||
test_assignment_operator_exists();
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#ifndef TEST_SUPPORT_ARCHETYPES_HPP
|
||||
#define TEST_SUPPORT_ARCHETYPES_HPP
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
|
||||
struct NoDefault {
|
||||
NoDefault() = delete;
|
||||
};
|
||||
|
||||
// Implicit copy/move types
|
||||
|
||||
struct AllCtors {
|
||||
AllCtors() = default;
|
||||
AllCtors(AllCtors const&) = default;
|
||||
AllCtors(AllCtors &&) = default;
|
||||
AllCtors& operator=(AllCtors const&) = default;
|
||||
AllCtors& operator=(AllCtors &&) = default;
|
||||
};
|
||||
|
||||
struct Copyable {
|
||||
Copyable() = default;
|
||||
Copyable(Copyable const &) = default;
|
||||
Copyable &operator=(Copyable const &) = default;
|
||||
};
|
||||
|
||||
struct CopyOnly {
|
||||
CopyOnly() = default;
|
||||
CopyOnly(CopyOnly const &) = default;
|
||||
CopyOnly &operator=(CopyOnly const &) = default;
|
||||
CopyOnly(CopyOnly &&) = delete;
|
||||
CopyOnly &operator=(CopyOnly &&) = delete;
|
||||
};
|
||||
|
||||
struct NonCopyable {
|
||||
NonCopyable() = default;
|
||||
NonCopyable(NonCopyable const &) = delete;
|
||||
NonCopyable &operator=(NonCopyable const &) = delete;
|
||||
};
|
||||
|
||||
struct MoveOnly {
|
||||
MoveOnly() = default;
|
||||
MoveOnly(MoveOnly &&) = default;
|
||||
MoveOnly &operator=(MoveOnly &&) = default;
|
||||
};
|
||||
|
||||
struct ConvertingType {
|
||||
ConvertingType() = default;
|
||||
ConvertingType(ConvertingType const&) = default;
|
||||
ConvertingType(ConvertingType &&) = default;
|
||||
ConvertingType& operator=(ConvertingType const&) = default;
|
||||
ConvertingType& operator=(ConvertingType &&) = default;
|
||||
template <class ...Args>
|
||||
ConvertingType(Args&&...) {}
|
||||
template <class Arg>
|
||||
ConvertingType& operator=(Arg&&) { return *this; }
|
||||
};
|
||||
|
||||
struct ExplicitConvertingType {
|
||||
ExplicitConvertingType() = default;
|
||||
explicit ExplicitConvertingType(ExplicitConvertingType const&) = default;
|
||||
explicit ExplicitConvertingType(ExplicitConvertingType &&) = default;
|
||||
ExplicitConvertingType& operator=(ExplicitConvertingType const&) = default;
|
||||
ExplicitConvertingType& operator=(ExplicitConvertingType &&) = default;
|
||||
template <class ...Args>
|
||||
explicit ExplicitConvertingType(Args&&...) {}
|
||||
template <class Arg>
|
||||
ExplicitConvertingType& operator=(Arg&&) { return *this; }
|
||||
};
|
||||
|
||||
// Explicit copy/move types
|
||||
|
||||
struct ExplicitAllCtors {
|
||||
explicit ExplicitAllCtors() = default;
|
||||
explicit ExplicitAllCtors(ExplicitAllCtors const&) = default;
|
||||
explicit ExplicitAllCtors(ExplicitAllCtors &&) = default;
|
||||
ExplicitAllCtors& operator=(ExplicitAllCtors const&) = default;
|
||||
ExplicitAllCtors& operator=(ExplicitAllCtors &&) = default;
|
||||
};
|
||||
|
||||
struct ExplicitCopyable {
|
||||
explicit ExplicitCopyable() = default;
|
||||
explicit ExplicitCopyable(ExplicitCopyable const &) = default;
|
||||
ExplicitCopyable &operator=(ExplicitCopyable const &) = default;
|
||||
};
|
||||
|
||||
struct ExplicitCopyOnly {
|
||||
explicit ExplicitCopyOnly() = default;
|
||||
explicit ExplicitCopyOnly(ExplicitCopyOnly const &) = default;
|
||||
ExplicitCopyOnly &operator=(ExplicitCopyOnly const &) = default;
|
||||
explicit ExplicitCopyOnly(ExplicitCopyOnly &&) = delete;
|
||||
ExplicitCopyOnly &operator=(ExplicitCopyOnly &&) = delete;
|
||||
};
|
||||
|
||||
struct ExplicitNonCopyable {
|
||||
explicit ExplicitNonCopyable() = default;
|
||||
explicit ExplicitNonCopyable(ExplicitNonCopyable const &) = delete;
|
||||
ExplicitNonCopyable &operator=(ExplicitNonCopyable const &) = delete;
|
||||
};
|
||||
|
||||
struct ExplicitMoveOnly {
|
||||
explicit ExplicitMoveOnly() = default;
|
||||
explicit ExplicitMoveOnly(ExplicitMoveOnly &&) = default;
|
||||
ExplicitMoveOnly &operator=(ExplicitMoveOnly &&) = default;
|
||||
};
|
||||
|
||||
#endif // TEST_STD_VER >= 11
|
||||
|
||||
#endif // TEST_SUPPORT_ARCHETYPES_HPP
|
|
@ -64,7 +64,7 @@
|
|||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4284">N4284</a></td><td>LWG</td></td><td>Contiguous Iterators.</td><td>Urbana</td><td>Complete</td><td>3.6</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4285">N4285</a></td><td>CWG</td></td><td>Cleanup for exception-specification and throw-expression.</td><td>Urbana</td><td></td><td></td></tr>
|
||||
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4387">N4387</a></td><td>LWG</td></td><td>improving pair and tuple</td><td>Lenexa</td><td></td><td></td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4387">N4387</a></td><td>LWG</td></td><td>improving pair and tuple</td><td>Lenexa</td><td>Complete</td><td>4.0</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4389">N4389</a></td><td>LWG</td></td><td>bool_constant</td><td>Lenexa</td><td>Complete</td><td>3.7</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4508">N4508</a></td><td>LWG</td></td><td>shared_mutex for C++17</td><td>Lenexa</td><td>Complete</td><td>3.7</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4366">N4366</a></td><td>LWG</td></td><td>LWG 2228 missing SFINAE rule</td><td>Lenexa</td><td>Complete</td><td>3.1</td></tr>
|
||||
|
|
Loading…
Reference in New Issue