Implement N4387, "Improving pair and tuple", and LWG 2367.

2015-06-30  Ville Voutilainen  <ville.voutilainen@gmail.com>

	Implement N4387, "Improving pair and tuple", and LWG 2367.

	* include/bits/stl_pair.h (_ConstructiblePair,
	_ImplicitlyConvertiblePair, _MoveConstructiblePair,
	_ImplicitlyMoveConvertiblePair): New.
	(pair()): Constrain it.
	(pair(const _T1&, const _T2&), pair(const pair<_U1, _U2>&),
	pair(_U1&&, const _T2&), pair(const _T1&, _U2&&), pair(_U1&&, _U2&&),
	pair(pair<_U1, _U2>&&)): Make conditionally explicit.
	* include/std/tuple (_TC, tuple::_TC2, tuple::TCC, tuple::TMC): New.
	(tuple()): Constrain it.
	(tuple(const _UElements&...), tuple(_UElements&&...),
	tuple(const tuple<_UElements...>&), tuple(tuple<_UElements...>&&),
	tuple(allocator_arg_t, const _Alloc&, const _UElements&...),
	tuple(allocator_arg_t, const _Alloc&, _UElements&&...),
	tuple(allocator_arg_t, const _Alloc&, const tuple<_UElements...>&),
	tuple(allocator_arg_t, const _Alloc&, tuple<_UElements...>&&),
	tuple(const pair<_U1, _U2>&), tuple(pair<_U1, _U2>&&),
	tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&),
	tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&)): Make
	conditionally explicit.
	* include/experimental/functional (__boyer_moore_array_base): Name
	array type explicitly instead of using an empty braced-init-list.
	* testsuite/20_util/pair/cons/explicit_construct.cc: New.
	* testsuite/20_util/pair/piecewise.cc: Use piecewise_construct.
	* testsuite/20_util/pair/requirements/dr2367.cc: New.
	* testsuite/20_util/tuple/cons/explicit_construct.cc: New.
	* testsuite/20_util/tuple/requirements/dr2367.cc: New.

From-SVN: r225189
This commit is contained in:
Ville Voutilainen 2015-06-30 16:26:49 +03:00 committed by Jonathan Wakely
parent fe95b0366a
commit bf7818bfb0
9 changed files with 1088 additions and 71 deletions

View File

@ -1,3 +1,34 @@
2015-06-30 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement N4387, "Improving pair and tuple", and LWG 2367.
* include/bits/stl_pair.h (_ConstructiblePair,
_ImplicitlyConvertiblePair, _MoveConstructiblePair,
_ImplicitlyMoveConvertiblePair): New.
(pair()): Constrain it.
(pair(const _T1&, const _T2&), pair(const pair<_U1, _U2>&),
pair(_U1&&, const _T2&), pair(const _T1&, _U2&&), pair(_U1&&, _U2&&),
pair(pair<_U1, _U2>&&)): Make conditionally explicit.
* include/std/tuple (_TC, tuple::_TC2, tuple::TCC, tuple::TMC): New.
(tuple()): Constrain it.
(tuple(const _UElements&...), tuple(_UElements&&...),
tuple(const tuple<_UElements...>&), tuple(tuple<_UElements...>&&),
tuple(allocator_arg_t, const _Alloc&, const _UElements&...),
tuple(allocator_arg_t, const _Alloc&, _UElements&&...),
tuple(allocator_arg_t, const _Alloc&, const tuple<_UElements...>&),
tuple(allocator_arg_t, const _Alloc&, tuple<_UElements...>&&),
tuple(const pair<_U1, _U2>&), tuple(pair<_U1, _U2>&&),
tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&),
tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&)): Make
conditionally explicit.
* include/experimental/functional (__boyer_moore_array_base): Name
array type explicitly instead of using an empty braced-init-list.
* testsuite/20_util/pair/cons/explicit_construct.cc: New.
* testsuite/20_util/pair/piecewise.cc: Use piecewise_construct.
* testsuite/20_util/pair/requirements/dr2367.cc: New.
* testsuite/20_util/tuple/cons/explicit_construct.cc: New.
* testsuite/20_util/tuple/requirements/dr2367.cc: New.
2015-06-30 Jonathan Wakely <jwakely@redhat.com>
* configure: Regenerate.

View File

@ -84,6 +84,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<std::size_t...>
struct _Index_tuple;
// Concept utility functions, reused in conditionally-explicit
// constructors.
template <typename _T1, typename _T2, typename _U1, typename _U2>
constexpr bool _ConstructiblePair()
{
return __and_<is_constructible<_T1, const _U1&>,
is_constructible<_T2, const _U2&>>::value;
}
template <typename _T1, typename _T2, typename _U1, typename _U2>
constexpr bool _ImplicitlyConvertiblePair()
{
return __and_<is_convertible<const _U1&, _T1>,
is_convertible<const _U2&, _T2>>::value;
}
template <typename _T1, typename _T2, typename _U1, typename _U2>
constexpr bool _MoveConstructiblePair()
{
return __and_<is_constructible<_T1, _U1&&>,
is_constructible<_T2, _U2&&>>::value;
}
template <typename _T1, typename _T2, typename _U1, typename _U2>
constexpr bool _ImplicitlyMoveConvertiblePair()
{
return __and_<is_convertible<_U1&&, _T1>,
is_convertible<_U2&&, _T2>>::value;
}
#endif
/**
@ -105,12 +137,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 265. std::pair::pair() effects overly restrictive
/** The default constructor creates @c first and @c second using their
* respective default constructors. */
#if __cplusplus >= 201103L
template <typename _U1 = _T1,
typename _U2 = _T2,
typename enable_if<__and_<
is_default_constructible<_U1>,
is_default_constructible<_U2>>
::value, bool>::type = true>
#endif
_GLIBCXX_CONSTEXPR pair()
: first(), second() { }
/** Two objects may be passed to a @c pair constructor to be copied. */
_GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b)
#if __cplusplus < 201103L
pair(const _T1& __a, const _T2& __b)
: first(__a), second(__b) { }
#else
template<typename _U1 = _T1, typename _U2=_T2, typename
enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
&& _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
bool>::type=true>
constexpr pair(const _T1& __a, const _T2& __b)
: first(__a), second(__b) { }
template<typename _U1 = _T1, typename _U2=_T2, typename
enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
&& !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
bool>::type=false>
explicit constexpr pair(const _T1& __a, const _T2& __b)
: first(__a), second(__b) { }
#endif
/** There is also a templated copy ctor for the @c pair class itself. */
#if __cplusplus < 201103L
@ -118,39 +174,99 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
#else
template<class _U1, class _U2, class = typename
enable_if<__and_<is_convertible<const _U1&, _T1>,
is_convertible<const _U2&, _T2>>::value>::type>
constexpr pair(const pair<_U1, _U2>& __p)
template<class _U1, class _U2, typename
enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
&& _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
bool>::type=true>
constexpr pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
template<class _U1, class _U2, typename
enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
&& !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
bool>::type=false>
explicit constexpr pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
constexpr pair(const pair&) = default;
constexpr pair(pair&&) = default;
// DR 811.
template<class _U1, class = typename
enable_if<is_convertible<_U1, _T1>::value>::type>
constexpr pair(_U1&& __x, const _T2& __y)
: first(std::forward<_U1>(__x)), second(__y) { }
template<class _U1, typename
enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>()
&& _MoveConstructiblePair<_T1, _T2, _U1, _T2>()
&& _ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>()
&& _ImplicitlyMoveConvertiblePair<_T1, _T2,
_U1, _T2>(),
bool>::type=true>
constexpr pair(_U1&& __x, const _T2& __y)
: first(std::forward<_U1>(__x)), second(__y) { }
template<class _U2, class = typename
enable_if<is_convertible<_U2, _T2>::value>::type>
constexpr pair(const _T1& __x, _U2&& __y)
: first(__x), second(std::forward<_U2>(__y)) { }
template<class _U1, typename
enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>()
&& _MoveConstructiblePair<_T1, _T2, _U1, _T2>()
&& (!_ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>()
|| !_ImplicitlyMoveConvertiblePair<_T1, _T2,
_U1, _T2>()),
bool>::type=false>
explicit constexpr pair(_U1&& __x, const _T2& __y)
: first(std::forward<_U1>(__x)), second(__y) { }
template<class _U1, class _U2, class = typename
enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>>::value>::type>
template<class _U2, typename
enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>()
&& _MoveConstructiblePair<_T1, _T2, _T1, _U2>()
&& _ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>()
&& _ImplicitlyMoveConvertiblePair<_T1, _T2,
_T1, _U2>(),
bool>::type=true>
constexpr pair(const _T1& __x, _U2&& __y)
: first(__x), second(std::forward<_U2>(__y)) { }
template<class _U2, typename
enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>()
&& _MoveConstructiblePair<_T1, _T2, _T1, _U2>()
&& (!_ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>()
|| !_ImplicitlyMoveConvertiblePair<_T1, _T2,
_T1, _U2>()),
bool>::type=false>
explicit pair(const _T1& __x, _U2&& __y)
: first(__x), second(std::forward<_U2>(__y)) { }
template<class _U1, class _U2, typename
enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
&& _ImplicitlyMoveConvertiblePair<_T1, _T2,
_U1, _U2>(),
bool>::type=true>
constexpr pair(_U1&& __x, _U2&& __y)
: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
template<class _U1, class _U2, class = typename
enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>>::value>::type>
template<class _U1, class _U2, typename
enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
&& !_ImplicitlyMoveConvertiblePair<_T1, _T2,
_U1, _U2>(),
bool>::type=false>
explicit constexpr pair(_U1&& __x, _U2&& __y)
: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
template<class _U1, class _U2, typename
enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
&& _ImplicitlyMoveConvertiblePair<_T1, _T2,
_U1, _U2>(),
bool>::type=true>
constexpr pair(pair<_U1, _U2>&& __p)
: first(std::forward<_U1>(__p.first)),
second(std::forward<_U2>(__p.second)) { }
template<class _U1, class _U2, typename
enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
&& !_ImplicitlyMoveConvertiblePair<_T1, _T2,
_U1, _U2>(),
bool>::type=false>
explicit constexpr pair(pair<_U1, _U2>&& __p)
: first(std::forward<_U1>(__p.first)),
second(std::forward<_U2>(__p.second)) { }
template<typename... _Args1, typename... _Args2>
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);

View File

@ -124,7 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _RAIter, typename _Unused>
__boyer_moore_array_base(_RAIter __pat, size_t __patlen,
_Unused&&, _Pred&& __pred)
: _M_bad_char{ {}, std::move(__pred) }
: _M_bad_char{ std::array<_Tp, _Len>{}, std::move(__pred) }
{
std::get<0>(_M_bad_char).fill(__patlen);
if (__patlen > 0)

View File

@ -457,63 +457,236 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
};
// Concept utility functions, reused in conditionally-explicit
// constructors.
template<bool, typename... _Elements>
struct _TC
{
template<typename... _UElements>
static constexpr bool _ConstructibleTuple()
{
return __and_<is_constructible<_Elements, const _UElements&>...>::value;
}
template<typename... _UElements>
static constexpr bool _ImplicitlyConvertibleTuple()
{
return __and_<is_convertible<const _UElements&, _Elements>...>::value;
}
template<typename... _UElements>
static constexpr bool _MoveConstructibleTuple()
{
return __and_<is_constructible<_Elements, _UElements&&>...>::value;
}
template<typename... _UElements>
static constexpr bool _ImplicitlyMoveConvertibleTuple()
{
return __and_<is_convertible<_UElements&&, _Elements>...>::value;
}
};
template<typename... _Elements>
struct _TC<false, _Elements...>
{
template<typename... _UElements>
static constexpr bool _ConstructibleTuple()
{
return false;
}
template<typename... _UElements>
static constexpr bool _ImplicitlyConvertibleTuple()
{
return false;
}
template<typename... _UElements>
static constexpr bool _MoveConstructibleTuple()
{
return false;
}
template<typename... _UElements>
static constexpr bool _ImplicitlyMoveConvertibleTuple()
{
return false;
}
};
/// Primary class template, tuple
template<typename... _Elements>
class tuple : public _Tuple_impl<0, _Elements...>
{
typedef _Tuple_impl<0, _Elements...> _Inherited;
// Used for constraining the default constructor so
// that it becomes dependent on the constraints.
template<typename _Dummy>
struct _TC2
{
static constexpr bool _DefaultConstructibleTuple()
{
return __and_<is_default_constructible<_Elements>...>::value;
}
};
public:
template<typename _Dummy = void,
typename enable_if<_TC2<_Dummy>::
_DefaultConstructibleTuple(),
bool>::type = true>
constexpr tuple()
: _Inherited() { }
explicit
constexpr tuple(const _Elements&... __elements)
// Shortcut for the cases where constructors taking _Elements...
// need to be constrained.
template<typename _Dummy> using _TCC =
_TC<is_same<_Dummy, void>::value,
_Elements...>;
template<typename _Dummy = void,
typename enable_if<
_TCC<_Dummy>::template
_ConstructibleTuple<_Elements...>()
&& _TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_Elements...>()
&& (sizeof...(_Elements) >= 1),
bool>::type=true>
constexpr tuple(const _Elements&... __elements)
: _Inherited(__elements...) { }
template<typename... _UElements, typename = typename
enable_if<__and_<is_convertible<_UElements,
_Elements>...>::value>::type>
explicit
template<typename _Dummy = void,
typename enable_if<
_TCC<_Dummy>::template
_ConstructibleTuple<_Elements...>()
&& !_TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_Elements...>()
&& (sizeof...(_Elements) >= 1),
bool>::type=false>
explicit constexpr tuple(const _Elements&... __elements)
: _Inherited(__elements...) { }
// Shortcut for the cases where constructors taking _UElements...
// need to be constrained.
template<typename... _UElements> using _TMC =
_TC<(sizeof...(_Elements) == sizeof...(_UElements)),
_Elements...>;
template<typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_MoveConstructibleTuple<_UElements...>()
&& _TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>()
&& (sizeof...(_Elements) >= 1),
bool>::type=true>
constexpr tuple(_UElements&&... __elements)
: _Inherited(std::forward<_UElements>(__elements)...) { }
template<typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_MoveConstructibleTuple<_UElements...>()
&& !_TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>()
&& (sizeof...(_Elements) >= 1),
bool>::type=false>
explicit constexpr tuple(_UElements&&... __elements)
: _Inherited(std::forward<_UElements>(__elements)...) { }
constexpr tuple(const tuple&) = default;
constexpr tuple(tuple&&) = default;
template<typename... _UElements, typename = typename
enable_if<__and_<is_convertible<const _UElements&,
_Elements>...>::value>::type>
template<typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_ConstructibleTuple<_UElements...>()
&& _TMC<_UElements...>::template
_ImplicitlyConvertibleTuple<_UElements...>(),
bool>::type=true>
constexpr tuple(const tuple<_UElements...>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
template<typename... _UElements, typename = typename
enable_if<__and_<is_convertible<_UElements,
_Elements>...>::value>::type>
template<typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_ConstructibleTuple<_UElements...>()
&& !_TMC<_UElements...>::template
_ImplicitlyConvertibleTuple<_UElements...>(),
bool>::type=false>
explicit constexpr tuple(const tuple<_UElements...>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
template<typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_MoveConstructibleTuple<_UElements...>()
&& _TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=true>
constexpr tuple(tuple<_UElements...>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
template<typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_MoveConstructibleTuple<_UElements...>()
&& !_TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=false>
explicit constexpr tuple(tuple<_UElements...>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
// Allocator-extended constructors.
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a)
: _Inherited(__tag, __a) { }
template<typename _Alloc>
template<typename _Alloc, typename _Dummy = void,
typename enable_if<
_TCC<_Dummy>::template
_ConstructibleTuple<_Elements...>()
&& _TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_Elements...>(),
bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const _Elements&... __elements)
: _Inherited(__tag, __a, __elements...) { }
template<typename _Alloc, typename... _UElements, typename = typename
enable_if<sizeof...(_UElements)
== sizeof...(_Elements)>::type>
template<typename _Alloc, typename _Dummy = void,
typename enable_if<
_TCC<_Dummy>::template
_ConstructibleTuple<_Elements...>()
&& !_TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_Elements...>(),
bool>::type=false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
const _Elements&... __elements)
: _Inherited(__tag, __a, __elements...) { }
template<typename _Alloc, typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_MoveConstructibleTuple<_UElements...>()
&& _TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
_UElements&&... __elements)
: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
{ }
template<typename _Alloc, typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_MoveConstructibleTuple<_UElements...>()
&& !_TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
_UElements&&... __elements)
: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
{ }
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
@ -522,24 +695,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
template<typename _Alloc, typename... _UElements, typename = typename
enable_if<sizeof...(_UElements)
== sizeof...(_Elements)>::type>
template<typename _Alloc, typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_ConstructibleTuple<_UElements...>()
&& _TMC<_UElements...>::template
_ImplicitlyConvertibleTuple<_UElements...>(),
bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const tuple<_UElements...>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
template<typename _Alloc, typename... _UElements, typename = typename
enable_if<sizeof...(_UElements)
== sizeof...(_Elements)>::type>
template<typename _Alloc, typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_ConstructibleTuple<_UElements...>()
&& !_TMC<_UElements...>::template
_ImplicitlyConvertibleTuple<_UElements...>(),
bool>::type=false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
const tuple<_UElements...>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
template<typename _Alloc, typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_MoveConstructibleTuple<_UElements...>()
&& _TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
tuple<_UElements...>&& __in)
: _Inherited(__tag, __a,
static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
{ }
template<typename _Alloc, typename... _UElements, typename
enable_if<_TMC<_UElements...>::template
_MoveConstructibleTuple<_UElements...>()
&& !_TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
tuple<_UElements...>&& __in)
: _Inherited(__tag, __a,
static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
{ }
tuple&
operator=(const tuple& __in)
{
@ -582,7 +785,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
// Explicit specialization, zero-element tuple.
template<>
template<>
class tuple<>
{
public:
@ -597,65 +800,190 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Tuple_impl<0, _T1, _T2> _Inherited;
public:
template <typename _U1 = _T1,
typename _U2 = _T2,
typename enable_if<__and_<
is_default_constructible<_U1>,
is_default_constructible<_U2>>
::value, bool>::type = true>
constexpr tuple()
: _Inherited() { }
explicit
constexpr tuple(const _T1& __a1, const _T2& __a2)
: _Inherited(__a1, __a2) { }
// Shortcut for the cases where constructors taking _T1, _T2
// need to be constrained.
template<typename _Dummy> using _TCC =
_TC<is_same<_Dummy, void>::value, _T1, _T2>;
template<typename _U1, typename _U2, typename = typename
enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>>::value>::type>
explicit
template<typename _Dummy = void, typename
enable_if<_TCC<_Dummy>::template
_ConstructibleTuple<_T1, _T2>()
&& _TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_T1, _T2>(),
bool>::type = true>
constexpr tuple(const _T1& __a1, const _T2& __a2)
: _Inherited(__a1, __a2) { }
template<typename _Dummy = void, typename
enable_if<_TCC<_Dummy>::template
_ConstructibleTuple<_T1, _T2>()
&& !_TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_T1, _T2>(),
bool>::type = false>
explicit constexpr tuple(const _T1& __a1, const _T2& __a2)
: _Inherited(__a1, __a2) { }
// Shortcut for the cases where constructors taking _U1, _U2
// need to be constrained.
using _TMC = _TC<true, _T1, _T2>;
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
constexpr tuple(_U1&& __a1, _U2&& __a2)
: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
constexpr tuple(const tuple&) = default;
constexpr tuple(tuple&&) = default;
template<typename _U1, typename _U2, typename = typename
enable_if<__and_<is_convertible<const _U1&, _T1>,
is_convertible<const _U2&, _T2>>::value>::type>
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_ConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = true>
constexpr tuple(const tuple<_U1, _U2>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
template<typename _U1, typename _U2, typename = typename
enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>>::value>::type>
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_ConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit constexpr tuple(const tuple<_U1, _U2>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
constexpr tuple(tuple<_U1, _U2>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
template<typename _U1, typename _U2, typename = typename
enable_if<__and_<is_convertible<const _U1&, _T1>,
is_convertible<const _U2&, _T2>>::value>::type>
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit constexpr tuple(tuple<_U1, _U2>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_ConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = true>
constexpr tuple(const pair<_U1, _U2>& __in)
: _Inherited(__in.first, __in.second) { }
template<typename _U1, typename _U2, typename = typename
enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>>::value>::type>
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_ConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit constexpr tuple(const pair<_U1, _U2>& __in)
: _Inherited(__in.first, __in.second) { }
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
constexpr tuple(pair<_U1, _U2>&& __in)
: _Inherited(std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
template<typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit constexpr tuple(pair<_U1, _U2>&& __in)
: _Inherited(std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
// Allocator-extended constructors.
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a)
: _Inherited(__tag, __a) { }
template<typename _Alloc>
template<typename _Alloc, typename _Dummy = void,
typename enable_if<
_TCC<_Dummy>::template
_ConstructibleTuple<_T1, _T2>()
&& _TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_T1, _T2>(),
bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const _T1& __a1, const _T2& __a2)
: _Inherited(__tag, __a, __a1, __a2) { }
template<typename _Alloc, typename _U1, typename _U2>
template<typename _Alloc, typename _Dummy = void,
typename enable_if<
_TCC<_Dummy>::template
_ConstructibleTuple<_T1, _T2>()
&& !_TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_T1, _T2>(),
bool>::type=false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
const _T1& __a1, const _T2& __a2)
: _Inherited(__tag, __a, __a1, __a2) { }
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
: _Inherited(__tag, __a, std::forward<_U1>(__a1),
std::forward<_U2>(__a2)) { }
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
_U1&& __a1, _U2&& __a2)
: _Inherited(__tag, __a, std::forward<_U1>(__a1),
std::forward<_U2>(__a2)) { }
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
@ -664,28 +992,92 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
template<typename _Alloc, typename _U1, typename _U2>
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_ConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const tuple<_U1, _U2>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
{ }
template<typename _Alloc, typename _U1, typename _U2>
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_ConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
const tuple<_U1, _U2>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
{ }
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
{ }
template<typename _Alloc, typename _U1, typename _U2>
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
tuple<_U1, _U2>&& __in)
: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
{ }
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_ConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const pair<_U1, _U2>& __in)
: _Inherited(__tag, __a, __in.first, __in.second) { }
template<typename _Alloc, typename _U1, typename _U2>
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_ConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
const pair<_U1, _U2>& __in)
: _Inherited(__tag, __a, __in.first, __in.second) { }
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
template<typename _Alloc, typename _U1, typename _U2, typename
enable_if<_TMC::template
_MoveConstructibleTuple<_U1, _U2>()
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
pair<_U1, _U2>&& __in)
: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
tuple&
operator=(const tuple& __in)
{

View File

@ -0,0 +1,108 @@
// { dg-do compile }
// { dg-options "-std=gnu++11" }
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <utility>
struct Explicit
{
Explicit() = default;
explicit Explicit(int) {}
};
std::pair<int, int> f1() {return {1,2};}
std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
std::pair<long, long> f3() {return std::pair<int, int>{1,2};}
std::pair<Explicit, Explicit> f4()
{
return std::pair<int, int>{1,2}; // { dg-error "could not convert" }
}
std::pair<long, long> f5() {return {1,2};}
std::pair<int, int> v0{1,2};
std::pair<Explicit, Explicit> v1{1,2};
std::pair<Explicit, Explicit> v2 = {1,2}; // { dg-error "explicit" }
std::pair<Explicit, Explicit> v3{std::pair<int,int>{1,2}};
std::pair<Explicit, Explicit> v4 =
std::pair<int,int>{1,2}; // { dg-error "conversion" }
std::pair<char *, char *> v5(0,0);
std::pair<long, long> v6{1,2};
std::pair<long, long> v7 = {1,2};
std::pair<long, long> v8{std::pair<int,int>{1,2}};
std::pair<long, long> v9 = std::pair<int,int>{1,2};
std::pair<Explicit, Explicit> v10{v0};
std::pair<Explicit, Explicit> v11 = v0; // { dg-error "conversion" }
std::pair<long, long> v12{v0};
std::pair<long, long> v13 = v0;
void f6(std::pair<Explicit, Explicit>) {}
void f7(std::pair<long, long>) {}
void test_arg_passing()
{
f6(v0); // { dg-error "could not convert" }
f6(v1);
f6({1,2}); // { dg-error "explicit" }
f6(std::pair<Explicit, Explicit>{});
f6(std::pair<int, int>{}); // { dg-error "could not convert" }
f7(v0);
f7(v6);
f7({1,2});
f7(std::pair<int, int>{});
f7(std::pair<long, long>{});
}
struct MoveOnly
{
MoveOnly() = default;
MoveOnly(MoveOnly&&) {}
};
struct ExplicitMoveOnly
{
ExplicitMoveOnly() = default;
ExplicitMoveOnly(ExplicitMoveOnly&&) {}
explicit ExplicitMoveOnly(MoveOnly&&) {}
};
std::pair<int*, ExplicitMoveOnly> v14{0, MoveOnly{}};
std::pair<ExplicitMoveOnly, int*> v15{MoveOnly{}, 0};
std::pair<int*, ExplicitMoveOnly> v16 =
{0, MoveOnly{}}; // { dg-error "explicit" }
std::pair<ExplicitMoveOnly, int*> v17 =
{MoveOnly{}, 0}; // { dg-error "explicit" }

View File

@ -69,20 +69,20 @@ void test01()
{
bool test __attribute__((unused)) = true;
std::pair<type_one, type_zero> pp0(std::piecewise_construct_t(),
std::pair<type_one, type_zero> pp0(std::piecewise_construct,
std::forward_as_tuple(-3),
std::forward_as_tuple());
VERIFY( pp0.first.get() == -3 );
VERIFY( pp0.second.get() == 757 );
std::pair<type_one, type_two> pp1(std::piecewise_construct_t(),
std::pair<type_one, type_two> pp1(std::piecewise_construct,
std::forward_as_tuple(6),
std::forward_as_tuple(5, 4));
VERIFY( pp1.first.get() == 6 );
VERIFY( pp1.second.get1() == 5 );
VERIFY( pp1.second.get2() == 4 );
std::pair<type_two, type_two> pp2(std::piecewise_construct_t(),
std::pair<type_two, type_two> pp2(std::piecewise_construct,
std::forward_as_tuple(2, 1),
std::forward_as_tuple(-1, -3));
VERIFY( pp2.first.get1() == 2 );

View File

@ -0,0 +1,41 @@
// { dg-do compile }
// { dg-options "-std=gnu++11" }
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <utility>
#include <type_traits>
// DR 2367, pair and tuple are not correctly implemented for is_constructible with no args
void test_default_constructible()
{
struct X
{
X() = delete;
};
typedef std::pair<int, X> P;
static_assert(!std::is_constructible<P>::value, "");
static_assert(!std::is_default_constructible<P>::value, "");
}
int main()
{
test_default_constructible();
return 0;
}

View File

@ -0,0 +1,282 @@
// { dg-do compile }
// { dg-options "-std=gnu++11" }
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <tuple>
#include <utility>
#include <memory>
struct Explicit
{
Explicit() = default;
explicit Explicit(int) {}
};
std::tuple<int> f1a() {return {1};}
std::tuple<int, int> f1b() {return {1,2};}
std::tuple<int, int, int> f1c() {return {1,2,3};}
std::tuple<Explicit> f2_a() {return {1};} // { dg-error "explicit" }
std::tuple<Explicit, Explicit> f2_b() {return {1,2};} // { dg-error "explicit" }
std::tuple<Explicit, Explicit, Explicit> f2_c() {return {1,2,3};} // { dg-error "explicit" }
std::tuple<long> f3_a() {return std::tuple<int>{1};}
std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};}
std::tuple<long, long, long> f3_c() {return std::tuple<int, int, int>{1,2,3};}
std::tuple<Explicit> f4_a()
{
return std::tuple<int>{1}; // { dg-error "could not convert" }
}
std::tuple<Explicit, Explicit> f4_b()
{
return std::tuple<int, int>{1,2}; // { dg-error "could not convert" }
}
std::tuple<Explicit, Explicit, Explicit> f4_c()
{
return std::tuple<int, int,int>{1,2,3}; // { dg-error "could not convert" }
}
std::tuple<long> f5_a() {return {1};}
std::tuple<long, long> f5_b() {return {1,2};}
std::tuple<long, long, long> f5_c() {return {1,2,3};}
std::tuple<int, int> fp1() {return std::pair<int, int>{1,2}; }
std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; }
std::tuple<Explicit, Explicit> fp3()
{return std::pair<int, int>{1,2}; } // { dg-error "could not convert" }
std::tuple<int> v0_a{1};
std::tuple<int, int> v0_b{1,2};
std::tuple<int, int, int> v0_c{1,2,3};
std::tuple<Explicit> v1_a{1};
std::tuple<Explicit, Explicit> v1_b{1,2};
std::tuple<Explicit, Explicit, Explicit> v1_c{1,2,3};
std::tuple<Explicit> v2_a = {1}; // { dg-error "explicit" }
std::tuple<Explicit, Explicit> v2_b = {1,2}; // { dg-error "explicit" }
std::tuple<Explicit, Explicit, Explicit> v2_c = {1,2,3}; // { dg-error "explicit" }
std::tuple<Explicit> v3_a{std::tuple<int>{1}};
std::tuple<Explicit, Explicit> v3_b{std::tuple<int,int>{1,2}};
std::tuple<Explicit, Explicit, Explicit> v3_c{std::tuple<int,int,int>{1,2,3}};
std::tuple<Explicit, Explicit> v4_a =
std::tuple<int>{1}; // { dg-error "conversion" }
std::tuple<Explicit, Explicit> v4_b =
std::tuple<int,int>{1,2}; // { dg-error "conversion" }
std::tuple<Explicit, Explicit, Explicit> v4_c =
std::tuple<int,int,int>{1,2,3}; // { dg-error "conversion" }
std::tuple<long> v6_a{1};
std::tuple<long, long> v6_b{1,2};
std::tuple<long, long, long> v6_c{1,2,3};
std::tuple<long> v7_a = {1};
std::tuple<long, long> v7_b = {1,2};
std::tuple<long, long, long> v7_c = {1,2,3};
std::tuple<long> v8_a{std::tuple<int>{1}};
std::tuple<long, long> v8_b{std::tuple<int,int>{1,2}};
std::tuple<long, long, long> v8_c{std::tuple<int,int,int>{1,2,3}};
std::tuple<long> v9_a = std::tuple<int>{1};
std::tuple<long, long> v9_b = std::tuple<int,int>{1,2};
std::tuple<long, long, long> v9_c = std::tuple<int,int,int>{1,2,3};
std::tuple<Explicit> v10_a{v0_a};
std::tuple<Explicit, Explicit> v10_b{v0_b};
std::tuple<Explicit, Explicit, Explicit> v10_c{v0_c};
std::tuple<Explicit> v11_a = v0_a; // { dg-error "conversion" }
std::tuple<Explicit, Explicit> v11_b = v0_b; // { dg-error "conversion" }
std::tuple<Explicit, Explicit, Explicit> v11_c
= v0_c; // { dg-error "conversion" }
std::tuple<long> v12_a{v0_a};
std::tuple<long, long> v12_b{v0_b};
std::tuple<long, long, long> v12_c{v0_c};
std::tuple<long> v13_a = v0_a;
std::tuple<long, long> v13_b = v0_b;
std::tuple<long, long, long> v13_c = v0_c;
std::tuple<int, int> v14{std::pair<int, int>{1,2}};
std::tuple<long, long> v15{std::pair<int, int>{1,2}};
std::tuple<Explicit, Explicit> v16{std::pair<int, int>{1,2}};
std::tuple<int, int> v17 = std::pair<int, int>{1,2};
std::tuple<long, long> v18 = std::pair<int, int>{1,2};
std::tuple<Explicit, Explicit> v19
= std::pair<int, int>{1,2}; // { dg-error "conversion" }
std::pair<int, int> v20;
std::tuple<int, int> v21{v20};
std::tuple<long, long> v22{v20};
std::tuple<Explicit, Explicit> v23{v20};
std::tuple<int, int> v24 = v20;
std::tuple<long, long> v25 = v20;
std::tuple<Explicit, Explicit> v26 = v20; // { dg-error "conversion" }
std::tuple<int> v27_a{std::allocator_arg, std::allocator<int>{}, 1};
std::tuple<int, int> v27_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
std::tuple<int, int, int> v27_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
std::tuple<long> v28_a{std::allocator_arg, std::allocator<int>{}, 1};
std::tuple<long, long> v28_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
std::tuple<long, long, long>
v28_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
std::tuple<Explicit> v29_a{std::allocator_arg, std::allocator<int>{}, 1};
std::tuple<Explicit, Explicit>
v29_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
std::tuple<Explicit, Explicit, Explicit>
v29_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
std::tuple<int> v30_a = {std::allocator_arg, std::allocator<int>{}, 1};
std::tuple<int, int> v30_b = {std::allocator_arg, std::allocator<int>{}, 1, 2};
std::tuple<int, int, int> v30_c
= {std::allocator_arg, std::allocator<int>{}, 1,2,3};
std::tuple<long> v31_a = {std::allocator_arg, std::allocator<int>{}, 1};
std::tuple<long, long> v31_b = {std::allocator_arg, std::allocator<int>{}, 1, 2};
std::tuple<long, long, long>
v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
std::tuple<Explicit> v32_a
= {std::allocator_arg, std::allocator<int>{}, 1}; // { dg-error "explicit" }
std::tuple<Explicit, Explicit> v32_b
= {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "explicit" }
std::tuple<Explicit, Explicit, Explicit> v32_c
= {std::allocator_arg, std::allocator<int>{}, 1,2,3}; // { dg-error "explicit" }
std::tuple<int, int> v33{std::allocator_arg, std::allocator<int>{},
std::pair<int, int>{1, 2}};
std::tuple<long, long> v34{std::allocator_arg, std::allocator<int>{},
std::pair<int, int>{1, 2}};
std::tuple<Explicit, Explicit>
v35{std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}};
std::tuple<int, int> v36 = {std::allocator_arg, std::allocator<int>{},
std::pair<int, int>{1, 2}};
std::tuple<long, long> v37 = {std::allocator_arg, std::allocator<int>{},
std::pair<int, int>{1, 2}};
std::tuple<Explicit, Explicit> v38
= {std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}}; // { dg-error "explicit" }
std::tuple<int, int> v39{std::allocator_arg, std::allocator<int>{}, v20};
std::tuple<long, long> v40{std::allocator_arg, std::allocator<int>{}, v20};
std::tuple<Explicit, Explicit>
v41{std::allocator_arg, std::allocator<int>{}, v20};
std::tuple<int, int> v42 = {std::allocator_arg, std::allocator<int>{}, v20};
std::tuple<long, long> v43 = {std::allocator_arg, std::allocator<int>{}, v20};
std::tuple<Explicit, Explicit> v44
= {std::allocator_arg, std::allocator<int>{}, v20}; // { dg-error "explicit" }
struct DeletedCopy
{
DeletedCopy(int);
DeletedCopy(const DeletedCopy&) = delete;
};
std::tuple<DeletedCopy> v45{42};
std::tuple<DeletedCopy> v46{std::allocator_arg,
std::allocator<DeletedCopy>{}, 42};
struct Sanity
{
int v;
};
std::tuple<int, Sanity> v47(3, {42});
std::tuple<int, int, Sanity> v48(3, 4, {42});
std::tuple<int, Sanity> v49(std::allocator_arg,
std::allocator<Sanity>{},
3, {42});
std::tuple<int, int, Sanity> v50(std::allocator_arg,
std::allocator<Sanity>{},
3, 4, {42});
void f6_a(std::tuple<Explicit>) {}
void f6_b(std::tuple<Explicit, Explicit>) {}
void f6_c(std::tuple<Explicit, Explicit, Explicit>) {}
void f7_a(std::tuple<long>) {}
void f7_b(std::tuple<long, long>) {}
void f7_c(std::tuple<long, long, long>) {}
void test_arg_passing()
{
f6_a(v0_a); // { dg-error "could not convert" }
f6_b(v0_b); // { dg-error "could not convert" }
f6_c(v0_c); // { dg-error "could not convert" }
f6_b(v20); // { dg-error "could not convert" }
f6_a(v1_a);
f6_b(v1_b);
f6_c(v1_c);
f6_a({1}); // { dg-error "explicit" }
f6_b({1,2}); // { dg-error "explicit" }
f6_c({1,2,3}); // { dg-error "explicit" }
f6_a(std::tuple<Explicit>{});
f6_b(std::tuple<Explicit, Explicit>{});
f6_c(std::tuple<Explicit, Explicit, Explicit>{});
f6_a(std::tuple<int>{}); // { dg-error "could not convert" }
f6_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
f6_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
f6_b(std::pair<int, int>{}); // { dg-error "could not convert" }
f7_a(v0_a);
f7_b(v0_b);
f7_c(v0_c);
f7_b(v20);
f7_a(v6_a);
f7_b(v6_b);
f7_c(v6_c);
f7_a({1});
f7_b({1,2});
f7_c({1,2,3});
f7_a(std::tuple<int>{});
f7_b(std::tuple<int, int>{});
f7_c(std::tuple<int, int, int>{});
f7_b(std::pair<int, int>{});
f7_a(std::tuple<long>{});
f7_b(std::tuple<long, long>{});
f7_c(std::tuple<long, long, long>{});
}

View File

@ -0,0 +1,47 @@
// { dg-do compile }
// { dg-options "-std=gnu++11" }
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <tuple>
#include <type_traits>
// DR 2367, pair and tuple are not correctly implemented for is_constructible with no args
void test_default_constructible()
{
struct X
{
X() = delete;
};
typedef std::tuple<int, X> T;
static_assert(!std::is_constructible<T>::value, "");
static_assert(!std::is_default_constructible<T>::value, "");
typedef std::tuple<int, int, X> T2;
static_assert(!std::is_constructible<T2>::value, "");
static_assert(!std::is_default_constructible<T2>::value, "");
}
int main()
{
test_default_constructible();
return 0;
}