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:
parent
fe95b0366a
commit
bf7818bfb0
@ -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.
|
||||
|
@ -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...>);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
108
libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
Normal file
108
libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
Normal 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" }
|
@ -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 );
|
||||
|
41
libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc
Normal file
41
libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc
Normal 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;
|
||||
}
|
282
libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
Normal file
282
libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
Normal 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>{});
|
||||
}
|
47
libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc
Normal file
47
libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user