Make the default constructors of tuple and pair conditionally explicit.

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.

From-SVN: r229699
This commit is contained in:
Ville Voutilainen 2015-11-03 10:41:40 +02:00 committed by Ville Voutilainen
parent bbe741d0e2
commit f763219373
12 changed files with 363 additions and 71 deletions

View File

@ -1,3 +1,33 @@
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> 2015-10-24 Jonathan Wakely <jwakely@redhat.com>
* include/std/functional (__invoke_impl): New overloads. * include/std/functional (__invoke_impl): New overloads.

View File

@ -141,13 +141,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _U1 = _T1, template <typename _U1 = _T1,
typename _U2 = _T2, typename _U2 = _T2,
typename enable_if<__and_< typename enable_if<__and_<
is_default_constructible<_U1>, __is_implicitly_default_constructible<_U1>,
is_default_constructible<_U2>> __is_implicitly_default_constructible<_U2>>
::value, bool>::type = true> ::value, bool>::type = true>
#endif #endif
_GLIBCXX_CONSTEXPR pair() _GLIBCXX_CONSTEXPR pair()
: first(), second() { } : 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. */ /** Two objects may be passed to a @c pair constructor to be copied. */
#if __cplusplus < 201103L #if __cplusplus < 201103L
pair(const _T1& __a, const _T2& __b) pair(const _T1& __a, const _T2& __b)

View File

@ -551,16 +551,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ {
return __and_<is_default_constructible<_Elements>...>::value; return __and_<is_default_constructible<_Elements>...>::value;
} }
static constexpr bool _ImplicitlyDefaultConstructibleTuple()
{
return __and_<__is_implicitly_default_constructible<_Elements>...>
::value;
}
}; };
public: public:
template<typename _Dummy = void, template<typename _Dummy = void,
typename enable_if<_TC2<_Dummy>:: typename enable_if<_TC2<_Dummy>::
_DefaultConstructibleTuple(), _ImplicitlyDefaultConstructibleTuple(),
bool>::type = true> bool>::type = true>
constexpr tuple() constexpr tuple()
: _Inherited() { } : _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... // Shortcut for the cases where constructors taking _Elements...
// need to be constrained. // need to be constrained.
template<typename _Dummy> using _TCC = template<typename _Dummy> using _TCC =
@ -837,13 +852,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _U1 = _T1, template <typename _U1 = _T1,
typename _U2 = _T2, typename _U2 = _T2,
typename enable_if<__and_< typename enable_if<__and_<
is_default_constructible<_U1>, __is_implicitly_default_constructible<_U1>,
is_default_constructible<_U2>> __is_implicitly_default_constructible<_U2>>
::value, bool>::type = true> ::value, bool>::type = true>
constexpr tuple() constexpr tuple()
: _Inherited() { } : _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 // Shortcut for the cases where constructors taking _T1, _T2
// need to be constrained. // need to be constrained.
template<typename _Dummy> using _TCC = template<typename _Dummy> using _TCC =

View File

@ -715,7 +715,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// is_unsigned /// is_unsigned
template<typename _Tp> template<typename _Tp>
struct is_unsigned struct is_unsigned
: public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>
{ }; { };
@ -744,7 +744,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> template<typename _Tp>
struct __is_array_unknown_bounds 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 // In N3290 is_destructible does not say anything about function
@ -862,7 +862,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> template<typename _Tp>
struct __is_default_constructible_atom struct __is_default_constructible_atom
: public __and_<__not_<is_void<_Tp>>, : 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> template<typename _Tp, bool = is_array<_Tp>::value>
@ -877,7 +877,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __is_default_constructible_safe<_Tp, true> struct __is_default_constructible_safe<_Tp, true>
: public __and_<__is_array_known_bounds<_Tp>, : public __and_<__is_array_known_bounds<_Tp>,
__is_default_constructible_atom<typename __is_default_constructible_atom<typename
remove_all_extents<_Tp>::type>>::type remove_all_extents<_Tp>::type>>
{ }; { };
template<typename _Tp> template<typename _Tp>
@ -957,7 +957,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Arg> template<typename _Tp, typename _Arg>
struct __is_direct_constructible_new_safe struct __is_direct_constructible_new_safe
: public __and_<is_destructible<_Tp>, : public __and_<is_destructible<_Tp>,
__is_direct_constructible_impl<_Tp, _Arg>>::type __is_direct_constructible_impl<_Tp, _Arg>>
{ }; { };
template<typename, typename> template<typename, typename>
@ -1029,7 +1029,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __and_<__is_static_castable<_Arg, _Tp>, : public __and_<__is_static_castable<_Arg, _Tp>,
__not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>, __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
__is_lvalue_to_rvalue_ref<_Arg, _Tp> __is_lvalue_to_rvalue_ref<_Arg, _Tp>
>>>::type >>>
{ }; { };
template<typename _Tp, typename _Arg> template<typename _Tp, typename _Arg>
@ -1144,7 +1144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __is_nt_default_constructible_impl<_Tp, true> struct __is_nt_default_constructible_impl<_Tp, true>
: public __and_<__is_array_known_bounds<_Tp>, : public __and_<__is_array_known_bounds<_Tp>,
__is_nt_default_constructible_atom<typename __is_nt_default_constructible_atom<typename
remove_all_extents<_Tp>::type>>::type remove_all_extents<_Tp>::type>>
{ }; { };
template<typename _Tp> template<typename _Tp>
@ -1156,7 +1156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> template<typename _Tp>
struct is_nothrow_default_constructible struct is_nothrow_default_constructible
: public __and_<is_default_constructible<_Tp>, : 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>
@ -1179,7 +1179,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename... _Args> template<typename _Tp, typename... _Args>
struct is_nothrow_constructible struct is_nothrow_constructible
: public __and_<is_constructible<_Tp, _Args...>, : 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, bool = __is_referenceable<_Tp>::value>
@ -1285,7 +1285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Up> template<typename _Tp, typename _Up>
struct is_nothrow_assignable struct is_nothrow_assignable
: public __and_<is_assignable<_Tp, _Up>, : 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, bool = __is_referenceable<_Tp>::value>
@ -1328,7 +1328,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename... _Args> template<typename _Tp, typename... _Args>
struct is_trivially_constructible struct is_trivially_constructible
: public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool, : public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool,
__is_trivially_constructible(_Tp, _Args...)>>::type __is_trivially_constructible(_Tp, _Args...)>>
{ }; { };
/// is_trivially_default_constructible /// is_trivially_default_constructible
@ -1337,12 +1337,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public is_trivially_constructible<_Tp>::type : 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 /// is_trivially_copy_constructible
template<typename _Tp> template<typename _Tp>
struct is_trivially_copy_constructible struct is_trivially_copy_constructible
: public __and_<is_copy_constructible<_Tp>, : public __and_<is_copy_constructible<_Tp>,
integral_constant<bool, integral_constant<bool,
__is_trivially_constructible(_Tp, const _Tp&)>>::type __is_trivially_constructible(_Tp, const _Tp&)>>
{ }; { };
/// is_trivially_move_constructible /// is_trivially_move_constructible
@ -1350,7 +1380,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct is_trivially_move_constructible struct is_trivially_move_constructible
: public __and_<is_move_constructible<_Tp>, : public __and_<is_move_constructible<_Tp>,
integral_constant<bool, integral_constant<bool,
__is_trivially_constructible(_Tp, _Tp&&)>>::type __is_trivially_constructible(_Tp, _Tp&&)>>
{ }; { };
/// is_trivially_assignable /// is_trivially_assignable
@ -1358,7 +1388,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct is_trivially_assignable struct is_trivially_assignable
: public __and_<is_assignable<_Tp, _Up>, : public __and_<is_assignable<_Tp, _Up>,
integral_constant<bool, integral_constant<bool,
__is_trivially_assignable(_Tp, _Up)>>::type __is_trivially_assignable(_Tp, _Up)>>
{ }; { };
/// is_trivially_copy_assignable /// is_trivially_copy_assignable
@ -1366,7 +1396,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct is_trivially_copy_assignable struct is_trivially_copy_assignable
: public __and_<is_copy_assignable<_Tp>, : public __and_<is_copy_assignable<_Tp>,
integral_constant<bool, integral_constant<bool,
__is_trivially_assignable(_Tp&, const _Tp&)>>::type __is_trivially_assignable(_Tp&, const _Tp&)>>
{ }; { };
/// is_trivially_move_assignable /// is_trivially_move_assignable
@ -1374,14 +1404,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct is_trivially_move_assignable struct is_trivially_move_assignable
: public __and_<is_move_assignable<_Tp>, : public __and_<is_move_assignable<_Tp>,
integral_constant<bool, integral_constant<bool,
__is_trivially_assignable(_Tp&, _Tp&&)>>::type __is_trivially_assignable(_Tp&, _Tp&&)>>
{ }; { };
/// is_trivially_destructible /// is_trivially_destructible
template<typename _Tp> template<typename _Tp>
struct is_trivially_destructible struct is_trivially_destructible
: public __and_<is_destructible<_Tp>, integral_constant<bool, : public __and_<is_destructible<_Tp>, integral_constant<bool,
__has_trivial_destructor(_Tp)>>::type __has_trivial_destructor(_Tp)>>
{ }; { };
/// has_trivial_default_constructor (temporary legacy) /// has_trivial_default_constructor (temporary legacy)

View File

@ -19,7 +19,7 @@
// with this library; see the file COPYING3. If not see // with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-error "static assertion failed" "" { target *-*-* } 2209 } // { dg-error "static assertion failed" "" { target *-*-* } 2239 }
#include <utility> #include <utility>

View File

@ -0,0 +1,27 @@
// { 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>;
}

View File

@ -0,0 +1,32 @@
// { 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;
}

View File

@ -0,0 +1,44 @@
// { 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, "");
}

View File

@ -48,4 +48,4 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 } // { 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 }

View File

@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 } // { dg-error "required from here" "" { target *-*-* } 42 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1770 } // { dg-error "invalid use of incomplete type" "" { target *-*-* } 1800 }
// { dg-error "declaration of" "" { target *-*-* } 1727 } // { dg-error "declaration of" "" { target *-*-* } 1757 }

View File

@ -26,6 +26,16 @@ struct Explicit
explicit Explicit(int) {} explicit Explicit(int) {}
}; };
struct ExplicitDefault
{
explicit ExplicitDefault() {}
};
struct ExplicitDefaultDefault
{
explicit ExplicitDefaultDefault() = default;
};
std::pair<int, int> f1() {return {1,2};} std::pair<int, int> f1() {return {1,2};}
std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" } std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
@ -72,6 +82,20 @@ void f6(std::pair<Explicit, Explicit>) {}
void f7(std::pair<long, long>) {} 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() void test_arg_passing()
{ {
f6(v0); // { dg-error "could not convert" } f6(v0); // { dg-error "could not convert" }
@ -84,6 +108,10 @@ void test_arg_passing()
f7({1,2}); f7({1,2});
f7(std::pair<int, int>{}); f7(std::pair<int, int>{});
f7(std::pair<long, long>{}); 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 struct MoveOnly

View File

@ -28,13 +28,26 @@ struct Explicit
explicit Explicit(int) {} explicit Explicit(int) {}
}; };
struct ExplicitDefault
{
explicit ExplicitDefault() {}
};
struct ExplicitDefaultDefault
{
explicit ExplicitDefaultDefault() = default;
};
std::tuple<int> f1a() {return {1};} std::tuple<int> f1a() {return {1};}
std::tuple<int, int> f1b() {return {1,2};} std::tuple<int, int> f1b() {return {1,2};}
std::tuple<int, int, int> f1c() {return {1,2,3};} std::tuple<int, int, int> f1c() {return {1,2,3};}
std::tuple<Explicit> f2_a() {return {1};} // { dg-error "explicit" } std::tuple<Explicit> f2_a()
std::tuple<Explicit, Explicit> f2_b() {return {1,2};} // { dg-error "explicit" } {return {1};} // { dg-error "explicit" }
std::tuple<Explicit, Explicit, Explicit> f2_c() {return {1,2,3};} // { 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> f3_a() {return std::tuple<int>{1};}
std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};} std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};}
@ -57,6 +70,24 @@ std::tuple<long> f5_a() {return {1};}
std::tuple<long, long> f5_b() {return {1,2};} std::tuple<long, long> f5_b() {return {1,2};}
std::tuple<long, long, long> f5_c() {return {1,2,3};} 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<int, int> fp1() {return std::pair<int, int>{1,2}; }
std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; } std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; }
std::tuple<Explicit, Explicit> fp3() std::tuple<Explicit, Explicit> fp3()
@ -163,7 +194,7 @@ std::tuple<long, long, long>
v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3}; v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
std::tuple<Explicit> v32_a 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::tuple<Explicit, Explicit> v32_b
= {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "explicit" } = {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "explicit" }
std::tuple<Explicit, Explicit, Explicit> v32_c std::tuple<Explicit, Explicit, Explicit> v32_c
@ -199,7 +230,19 @@ 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<long, long> v43 = {std::allocator_arg, std::allocator<int>{}, v20};
std::tuple<Explicit, Explicit> v44 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 struct DeletedCopy
{ {
@ -225,58 +268,73 @@ std::tuple<int, int, Sanity> v50(std::allocator_arg,
std::allocator<Sanity>{}, std::allocator<Sanity>{},
3, 4, {42}); 3, 4, {42});
void f6_a(std::tuple<Explicit>) {} void f8_a(std::tuple<Explicit>) {}
void f6_b(std::tuple<Explicit, Explicit>) {} void f8_b(std::tuple<Explicit, Explicit>) {}
void f6_c(std::tuple<Explicit, Explicit, Explicit>) {} void f8_c(std::tuple<Explicit, Explicit, Explicit>) {}
void f7_a(std::tuple<long>) {} void f9_a(std::tuple<long>) {}
void f7_b(std::tuple<long, long>) {} void f9_b(std::tuple<long, long>) {}
void f7_c(std::tuple<long, long, long>) {} void f9_c(std::tuple<long, long, long>) {}
void f10_a(std::tuple<ExplicitDefault>) {}
void f10_b(std::tuple<ExplicitDefault, int>) {}
void f11_a(std::tuple<ExplicitDefaultDefault>) {}
void f11_b(std::tuple<ExplicitDefaultDefault, int>) {}
void test_arg_passing() void test_arg_passing()
{ {
f6_a(v0_a); // { dg-error "could not convert" } f8_a(v0_a); // { dg-error "could not convert" }
f6_b(v0_b); // { dg-error "could not convert" } f8_b(v0_b); // { dg-error "could not convert" }
f6_c(v0_c); // { dg-error "could not convert" } f8_c(v0_c); // { dg-error "could not convert" }
f6_b(v20); // { dg-error "could not convert" } f8_b(v20); // { dg-error "could not convert" }
f6_a(v1_a); f8_a(v1_a);
f6_b(v1_b); f8_b(v1_b);
f6_c(v1_c); f8_c(v1_c);
f6_a({1}); // { dg-error "explicit" } f8_a({1}); // { dg-error "explicit" }
f6_b({1,2}); // { dg-error "explicit" } f8_b({1,2}); // { dg-error "explicit" }
f6_c({1,2,3}); // { dg-error "explicit" } f8_c({1,2,3}); // { dg-error "explicit" }
f6_a(std::tuple<Explicit>{}); f8_a(std::tuple<Explicit>{});
f6_b(std::tuple<Explicit, Explicit>{}); f8_b(std::tuple<Explicit, Explicit>{});
f6_c(std::tuple<Explicit, Explicit, Explicit>{}); f8_c(std::tuple<Explicit, Explicit, Explicit>{});
f6_a(std::tuple<int>{}); // { dg-error "could not convert" } f8_a(std::tuple<int>{}); // { dg-error "could not convert" }
f6_b(std::tuple<int, int>{}); // { dg-error "could not convert" } f8_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
f6_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" } f8_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
f6_b(std::pair<int, int>{}); // { dg-error "could not convert" } f8_b(std::pair<int, int>{}); // { dg-error "could not convert" }
f7_a(v0_a); f9_a(v0_a);
f7_b(v0_b); f9_b(v0_b);
f7_c(v0_c); f9_c(v0_c);
f7_b(v20); f9_b(v20);
f7_a(v6_a); f9_a(v6_a);
f7_b(v6_b); f9_b(v6_b);
f7_c(v6_c); f9_c(v6_c);
f7_a({1}); f9_a({1});
f7_b({1,2}); f9_b({1,2});
f7_c({1,2,3}); f9_c({1,2,3});
f7_a(std::tuple<int>{}); f9_a(std::tuple<int>{});
f7_b(std::tuple<int, int>{}); f9_b(std::tuple<int, int>{});
f7_c(std::tuple<int, int, int>{}); f9_c(std::tuple<int, int, int>{});
f7_b(std::pair<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>{});
f7_a(std::tuple<long>{}); f10_a({}); // { dg-error "explicit" }
f7_b(std::tuple<long, long>{}); f10_b({}); // { dg-error "explicit" }
f7_c(std::tuple<long, long, long>{}); 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>{});
} }