+2015-11-03 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ Make the default constructors of tuple and pair conditionally explicit.
+ * include/std/type_traits (is_unsigned, __is_array_unknown_bounds,
+ __is_default_constructible_atom, __is_default_constructible_safe,
+ __is_direct_constructible_new_safe, __is_direct_constructible_ref_cast,
+ __is_nt_default_constructible_impl, is_nothrow_default_constructible,
+ is_nothrow_constructible, is_nothrow_assignable,
+ is_trivially_constructible, is_trivially_copy_constructible,
+ is_trivially_move_constructible, is_trivially_assignable,
+ is_trivially_copy_assignable, is_trivially_move_assignable,
+ is_trivially_destructible): Simplify.
+ * include/std/type_traits (
+ __do_is_implicitly_default_constructible_impl,
+ __is_implicitly_default_constructible_impl,
+ __is_implicitly_default_constructible_safe,
+ __is_implicitly_default_constructible): New.
+ * include/bits/stl_pair.h (pair::pair()): Use it.
+ * include/std/tuple (tuple<_T1, _T2>::tuple): Use it.
+ * include/std/tuple (_ImplicitlyDefaultConstructibleTuple): New.
+ * include/std/tuple (tuple<_Types...>::tuple()): Use it.
+ * testsuite/20_util/declval/requirements/1_neg.cc: Adjust.
+ * testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc: New.
+ * testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc: Likewise.
+ * testsuite/20_util/is_implicitly_default_constructible/value.cc: Likewise.
+ * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust.
+ * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Likewise.
+ * testsuite/20_util/pair/cons/explicit_construct.cc: Likewise.
+ * testsuite/20_util/tuple/cons/explicit_construct.cc: Likewise.
+
2015-10-24 Jonathan Wakely <jwakely@redhat.com>
* include/std/functional (__invoke_impl): New overloads.
template <typename _U1 = _T1,
typename _U2 = _T2,
typename enable_if<__and_<
- is_default_constructible<_U1>,
- is_default_constructible<_U2>>
+ __is_implicitly_default_constructible<_U1>,
+ __is_implicitly_default_constructible<_U2>>
::value, bool>::type = true>
#endif
_GLIBCXX_CONSTEXPR pair()
: first(), second() { }
+#if __cplusplus >= 201103L
+ template <typename _U1 = _T1,
+ typename _U2 = _T2,
+ typename enable_if<__and_<
+ is_default_constructible<_U1>,
+ is_default_constructible<_U2>,
+ __not_<
+ __and_<__is_implicitly_default_constructible<_U1>,
+ __is_implicitly_default_constructible<_U2>>>>
+ ::value, bool>::type = false>
+ explicit constexpr pair()
+ : first(), second() { }
+#endif
+
/** Two objects may be passed to a @c pair constructor to be copied. */
#if __cplusplus < 201103L
pair(const _T1& __a, const _T2& __b)
{
return __and_<is_default_constructible<_Elements>...>::value;
}
+ static constexpr bool _ImplicitlyDefaultConstructibleTuple()
+ {
+ return __and_<__is_implicitly_default_constructible<_Elements>...>
+ ::value;
+ }
};
public:
template<typename _Dummy = void,
typename enable_if<_TC2<_Dummy>::
- _DefaultConstructibleTuple(),
+ _ImplicitlyDefaultConstructibleTuple(),
bool>::type = true>
constexpr tuple()
: _Inherited() { }
+ template<typename _Dummy = void,
+ typename enable_if<_TC2<_Dummy>::
+ _DefaultConstructibleTuple()
+ &&
+ !_TC2<_Dummy>::
+ _ImplicitlyDefaultConstructibleTuple(),
+ bool>::type = false>
+ explicit constexpr tuple()
+ : _Inherited() { }
+
// Shortcut for the cases where constructors taking _Elements...
// need to be constrained.
template<typename _Dummy> using _TCC =
template <typename _U1 = _T1,
typename _U2 = _T2,
typename enable_if<__and_<
- is_default_constructible<_U1>,
- is_default_constructible<_U2>>
+ __is_implicitly_default_constructible<_U1>,
+ __is_implicitly_default_constructible<_U2>>
::value, bool>::type = true>
constexpr tuple()
: _Inherited() { }
+ template <typename _U1 = _T1,
+ typename _U2 = _T2,
+ typename enable_if<
+ __and_<
+ is_default_constructible<_U1>,
+ is_default_constructible<_U2>,
+ __not_<
+ __and_<__is_implicitly_default_constructible<_U1>,
+ __is_implicitly_default_constructible<_U2>>>>
+ ::value, bool>::type = false>
+
+ explicit constexpr tuple()
+ : _Inherited() { }
+
// Shortcut for the cases where constructors taking _T1, _T2
// need to be constrained.
template<typename _Dummy> using _TCC =
/// is_unsigned
template<typename _Tp>
struct is_unsigned
- : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
+ : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>
{ };
template<typename _Tp>
struct __is_array_unknown_bounds
- : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
+ : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>
{ };
// In N3290 is_destructible does not say anything about function
template<typename _Tp>
struct __is_default_constructible_atom
: public __and_<__not_<is_void<_Tp>>,
- __is_default_constructible_impl<_Tp>>::type
+ __is_default_constructible_impl<_Tp>>
{ };
template<typename _Tp, bool = is_array<_Tp>::value>
struct __is_default_constructible_safe<_Tp, true>
: public __and_<__is_array_known_bounds<_Tp>,
__is_default_constructible_atom<typename
- remove_all_extents<_Tp>::type>>::type
+ remove_all_extents<_Tp>::type>>
{ };
template<typename _Tp>
template<typename _Tp, typename _Arg>
struct __is_direct_constructible_new_safe
: public __and_<is_destructible<_Tp>,
- __is_direct_constructible_impl<_Tp, _Arg>>::type
+ __is_direct_constructible_impl<_Tp, _Arg>>
{ };
template<typename, typename>
: public __and_<__is_static_castable<_Arg, _Tp>,
__not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
__is_lvalue_to_rvalue_ref<_Arg, _Tp>
- >>>::type
+ >>>
{ };
template<typename _Tp, typename _Arg>
struct __is_nt_default_constructible_impl<_Tp, true>
: public __and_<__is_array_known_bounds<_Tp>,
__is_nt_default_constructible_atom<typename
- remove_all_extents<_Tp>::type>>::type
+ remove_all_extents<_Tp>::type>>
{ };
template<typename _Tp>
template<typename _Tp>
struct is_nothrow_default_constructible
: public __and_<is_default_constructible<_Tp>,
- __is_nt_default_constructible_impl<_Tp>>::type
+ __is_nt_default_constructible_impl<_Tp>>
{ };
template<typename _Tp, typename... _Args>
template<typename _Tp, typename... _Args>
struct is_nothrow_constructible
: public __and_<is_constructible<_Tp, _Args...>,
- __is_nt_constructible_impl<_Tp, _Args...>>::type
+ __is_nt_constructible_impl<_Tp, _Args...>>
{ };
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
template<typename _Tp, typename _Up>
struct is_nothrow_assignable
: public __and_<is_assignable<_Tp, _Up>,
- __is_nt_assignable_impl<_Tp, _Up>>::type
+ __is_nt_assignable_impl<_Tp, _Up>>
{ };
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
template<typename _Tp, typename... _Args>
struct is_trivially_constructible
: public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool,
- __is_trivially_constructible(_Tp, _Args...)>>::type
+ __is_trivially_constructible(_Tp, _Args...)>>
{ };
/// is_trivially_default_constructible
: public is_trivially_constructible<_Tp>::type
{ };
+ struct __do_is_implicitly_default_constructible_impl
+ {
+ template <typename _Tp>
+ static void __helper(const _Tp&);
+
+ template <typename _Tp>
+ static true_type __test(const _Tp&,
+ decltype(__helper<const _Tp&>({}))* = 0);
+
+ static false_type __test(...);
+ };
+
+ template<typename _Tp>
+ struct __is_implicitly_default_constructible_impl
+ : public __do_is_implicitly_default_constructible_impl
+ {
+ typedef decltype(__test(declval<_Tp>())) type;
+ };
+
+ template<typename _Tp>
+ struct __is_implicitly_default_constructible_safe
+ : public __is_implicitly_default_constructible_impl<_Tp>::type
+ { };
+
+ template <typename _Tp>
+ struct __is_implicitly_default_constructible
+ : public __and_<is_default_constructible<_Tp>,
+ __is_implicitly_default_constructible_safe<_Tp>>
+ { };
+
/// is_trivially_copy_constructible
template<typename _Tp>
struct is_trivially_copy_constructible
: public __and_<is_copy_constructible<_Tp>,
integral_constant<bool,
- __is_trivially_constructible(_Tp, const _Tp&)>>::type
+ __is_trivially_constructible(_Tp, const _Tp&)>>
{ };
/// is_trivially_move_constructible
struct is_trivially_move_constructible
: public __and_<is_move_constructible<_Tp>,
integral_constant<bool,
- __is_trivially_constructible(_Tp, _Tp&&)>>::type
+ __is_trivially_constructible(_Tp, _Tp&&)>>
{ };
/// is_trivially_assignable
struct is_trivially_assignable
: public __and_<is_assignable<_Tp, _Up>,
integral_constant<bool,
- __is_trivially_assignable(_Tp, _Up)>>::type
+ __is_trivially_assignable(_Tp, _Up)>>
{ };
/// is_trivially_copy_assignable
struct is_trivially_copy_assignable
: public __and_<is_copy_assignable<_Tp>,
integral_constant<bool,
- __is_trivially_assignable(_Tp&, const _Tp&)>>::type
+ __is_trivially_assignable(_Tp&, const _Tp&)>>
{ };
/// is_trivially_move_assignable
struct is_trivially_move_assignable
: public __and_<is_move_assignable<_Tp>,
integral_constant<bool,
- __is_trivially_assignable(_Tp&, _Tp&&)>>::type
+ __is_trivially_assignable(_Tp&, _Tp&&)>>
{ };
/// is_trivially_destructible
template<typename _Tp>
struct is_trivially_destructible
: public __and_<is_destructible<_Tp>, integral_constant<bool,
- __has_trivial_destructor(_Tp)>>::type
+ __has_trivial_destructor(_Tp)>>
{ };
/// has_trivial_default_constructor (temporary legacy)
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "static assertion failed" "" { target *-*-* } 2209 }
+// { dg-error "static assertion failed" "" { target *-*-* } 2239 }
#include <utility>
--- /dev/null
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// 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 <type_traits>
+
+namespace std
+{
+ typedef short test_type;
+ template struct std::__is_implicitly_default_constructible<test_type>;
+}
--- /dev/null
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// 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 <type_traits>
+
+
+void test01()
+{
+ // Check for required typedefs
+ typedef std::__is_implicitly_default_constructible<int> test_type;
+ typedef test_type::value_type value_type;
+ typedef test_type::type type;
+ typedef test_type::type::value_type type_value_type;
+ typedef test_type::type::type type_type;
+}
--- /dev/null
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// 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 <type_traits>
+
+struct ExplicitDefault
+{
+ explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+ explicit ExplicitDefaultDefault() = default;
+};
+
+void test01()
+{
+ using std::__is_implicitly_default_constructible;
+ // Positive tests.
+ static_assert(__is_implicitly_default_constructible<int>::value, "");
+ // Negative tests.
+ static_assert(!__is_implicitly_default_constructible<int&>::value, "");
+ static_assert(!__is_implicitly_default_constructible<
+ ExplicitDefault>::value, "");
+ static_assert(!__is_implicitly_default_constructible<
+ ExplicitDefaultDefault>::value, "");
+}
// { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 }
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1874 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1904 }
// { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 }
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1770 }
-// { dg-error "declaration of" "" { target *-*-* } 1727 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1800 }
+// { dg-error "declaration of" "" { target *-*-* } 1757 }
explicit Explicit(int) {}
};
+struct ExplicitDefault
+{
+ explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+ explicit ExplicitDefaultDefault() = default;
+};
+
std::pair<int, int> f1() {return {1,2};}
std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
void f7(std::pair<long, long>) {}
+std::pair<ExplicitDefault, int> f8()
+{
+ return {}; // { dg-error "explicit" }
+}
+
+std::pair<ExplicitDefaultDefault, int> f9()
+{
+ return {}; // { dg-error "explicit" }
+}
+
+void f10(std::pair<ExplicitDefault, int>) {}
+
+void f11(std::pair<ExplicitDefaultDefault, int>) {}
+
void test_arg_passing()
{
f6(v0); // { dg-error "could not convert" }
f7({1,2});
f7(std::pair<int, int>{});
f7(std::pair<long, long>{});
+ f10({}); // { dg-error "explicit" }
+ f11({}); // { dg-error "explicit" }
+ f10(std::pair<ExplicitDefault, int>{});
+ f11(std::pair<ExplicitDefaultDefault, int>{});
}
struct MoveOnly
explicit Explicit(int) {}
};
+struct ExplicitDefault
+{
+ explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+ explicit ExplicitDefaultDefault() = default;
+};
+
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<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> f5_b() {return {1,2};}
std::tuple<long, long, long> f5_c() {return {1,2,3};}
+std::tuple<ExplicitDefault> f6_a()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, ExplicitDefault> f6_b()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, ExplicitDefault, ExplicitDefault> f6_c()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, int> f6_d()
+{return {};} // { dg-error "explicit" }
+
+std::tuple<ExplicitDefaultDefault> f7_a()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault, ExplicitDefaultDefault> f7_b()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault,
+ ExplicitDefaultDefault,
+ ExplicitDefaultDefault> f7_c()
+{return {};} // { dg-error "explicit" }
+
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()
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::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::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" }
+= {std::allocator_arg, std::allocator<int>{ }, v20}; // { dg-error "explicit" }
+std::tuple<ExplicitDefault> v45_a{};
+std::tuple<ExplicitDefault, int> v45_b{};
+
+std::tuple<ExplicitDefault> v46_a = {}; // { dg-error "explicit" }
+std::tuple<ExplicitDefault, int> v46_b = {}; // { dg-error "explicit" }
+
+std::tuple<ExplicitDefaultDefault> v47_a{};
+std::tuple<ExplicitDefaultDefault, int> v47_b{};
+
+std::tuple<ExplicitDefaultDefault> v48_a = {}; // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault, int> v48_b = { }; // { dg-error "explicit" }
+
struct DeletedCopy
{
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 f8_a(std::tuple<Explicit>) {}
+void f8_b(std::tuple<Explicit, Explicit>) {}
+void f8_c(std::tuple<Explicit, Explicit, Explicit>) {}
+
+void f9_a(std::tuple<long>) {}
+void f9_b(std::tuple<long, long>) {}
+void f9_c(std::tuple<long, long, long>) {}
+
+void f10_a(std::tuple<ExplicitDefault>) {}
+void f10_b(std::tuple<ExplicitDefault, int>) {}
-void f7_a(std::tuple<long>) {}
-void f7_b(std::tuple<long, long>) {}
-void f7_c(std::tuple<long, long, long>) {}
+void f11_a(std::tuple<ExplicitDefaultDefault>) {}
+void f11_b(std::tuple<ExplicitDefaultDefault, int>) {}
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>{});
+ f8_a(v0_a); // { dg-error "could not convert" }
+ f8_b(v0_b); // { dg-error "could not convert" }
+ f8_c(v0_c); // { dg-error "could not convert" }
+ f8_b(v20); // { dg-error "could not convert" }
+
+ f8_a(v1_a);
+ f8_b(v1_b);
+ f8_c(v1_c);
+
+ f8_a({1}); // { dg-error "explicit" }
+ f8_b({1,2}); // { dg-error "explicit" }
+ f8_c({1,2,3}); // { dg-error "explicit" }
+
+ f8_a(std::tuple<Explicit>{});
+ f8_b(std::tuple<Explicit, Explicit>{});
+ f8_c(std::tuple<Explicit, Explicit, Explicit>{});
+
+ f8_a(std::tuple<int>{}); // { dg-error "could not convert" }
+ f8_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
+ f8_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
+ f8_b(std::pair<int, int>{}); // { dg-error "could not convert" }
+
+ f9_a(v0_a);
+ f9_b(v0_b);
+ f9_c(v0_c);
+ f9_b(v20);
+
+ f9_a(v6_a);
+ f9_b(v6_b);
+ f9_c(v6_c);
+
+ f9_a({1});
+ f9_b({1,2});
+ f9_c({1,2,3});
+
+ f9_a(std::tuple<int>{});
+ f9_b(std::tuple<int, int>{});
+ f9_c(std::tuple<int, int, int>{});
+ f9_b(std::pair<int, int>{});
+
+ f9_a(std::tuple<long>{});
+ f9_b(std::tuple<long, long>{});
+ f9_c(std::tuple<long, long, long>{});
+
+ f10_a({}); // { dg-error "explicit" }
+ f10_b({}); // { dg-error "explicit" }
+ f11_a({}); // { dg-error "explicit" }
+ f11_b({}); // { dg-error "explicit" }
+
+ f10_a(std::tuple<ExplicitDefault>{});
+ f10_b(std::tuple<ExplicitDefault, int>{});
+ f11_a(std::tuple<ExplicitDefaultDefault>{});
+ f11_b(std::tuple<ExplicitDefaultDefault, int>{});
}