+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.
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
/**
// 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
template<class _U1, class _U2>
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 _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, class _U2, class = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ 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 _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 _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...>);
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)
}
};
+
+ // 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)) { }
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)
{
};
// Explicit specialization, zero-element tuple.
- template<>
+ template<>
class tuple<>
{
public:
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) { }
-
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
- explicit
+ // 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 _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)) { }
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)
{
--- /dev/null
+// { 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" }
{
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 );
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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>{});
+}
--- /dev/null
+// { 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;
+}