Implement the std::pair parts of "Improving pair and tuple". Completes N4387.

llvm-svn: 276605
This commit is contained in:
Eric Fiselier 2016-07-25 04:32:07 +00:00
parent 126de5d4b4
commit 4927c29577
14 changed files with 1016 additions and 181 deletions

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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
}

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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
}

View File

@ -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}}
}
}

View File

@ -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
}

View File

@ -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();
}

View File

@ -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

View File

@ -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>