From 61ad58f3aa6aac0e9b91e175dd821388c5fdf320 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 23 Jan 2017 15:56:05 +0000 Subject: [PATCH] PR libstdc++/79195 fix make_array type deduction PR libstdc++/79195 * include/experimental/array (__make_array_elem): New class template and partial specialization. (__is_reference_wrapper): Move into __make_array_elem specialization. (make_array): Use __make_array_elem to determine element type and move static assertion into specialization. Qualify std::forward call. (to_array): Add exception specifiation. * testsuite/experimental/array/make_array.cc: Test argument types without a common type. * testsuite/experimental/array/neg.cc: Adjust expected error message. From-SVN: r244813 --- libstdc++-v3/ChangeLog | 13 ++++++ libstdc++-v3/include/experimental/array | 46 +++++++++++-------- .../experimental/array/make_array.cc | 13 +++++- .../testsuite/experimental/array/neg.cc | 2 +- 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1da3a365cf2..9bd2c7efd10 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2017-01-23 Jonathan Wakely + + PR libstdc++/79195 + * include/experimental/array (__make_array_elem): New class template + and partial specialization. + (__is_reference_wrapper): Move into __make_array_elem specialization. + (make_array): Use __make_array_elem to determine element type and move + static assertion into specialization. Qualify std::forward call. + (to_array): Add exception specifiation. + * testsuite/experimental/array/make_array.cc: Test argument types + without a common type. + * testsuite/experimental/array/neg.cc: Adjust expected error message. + 2017-01-22 Gerald Pfeifer * doc/xml/manual/debug.xml: code.google.com uses https now. diff --git a/libstdc++-v3/include/experimental/array b/libstdc++-v3/include/experimental/array index 5899486ff39..11cb924e087 100644 --- a/libstdc++-v3/include/experimental/array +++ b/libstdc++-v3/include/experimental/array @@ -57,35 +57,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ -template - struct __is_reference_wrapper : false_type - {}; +template + struct __make_array_elem + { + using type = _Dest; + }; + +template + struct __make_array_elem + : common_type<_Types...> + { + template + struct __is_reference_wrapper : false_type + {}; + + template + struct __is_reference_wrapper> : true_type + {}; -template - struct __is_reference_wrapper> : true_type - {}; + static_assert(!__or_<__is_reference_wrapper>...>::value, + "make_array must be used with an explicit target type when" + "any of the arguments is a reference_wrapper"); + }; template - constexpr auto + constexpr + array::type, sizeof...(_Types)> make_array(_Types&&... __t) - -> array, - common_type_t<_Types...>, - _Dest>, - sizeof...(_Types)> { - static_assert(__or_< - __not_>, - __and_<__not_<__is_reference_wrapper>>...>> - ::value, - "make_array cannot be used without an explicit target type " - "if any of the types given is a reference_wrapper"); - return {{forward<_Types>(__t)...}}; + return {{ std::forward<_Types>(__t)... }}; } template constexpr array, _Nm> - __to_array(_Tp (&__a)[_Nm], - index_sequence<_Idx...>) + __to_array(_Tp (&__a)[_Nm], index_sequence<_Idx...>) { return {{__a[_Idx]...}}; } @@ -93,6 +98,7 @@ template template constexpr array, _Nm> to_array(_Tp (&__a)[_Nm]) + noexcept(is_nothrow_constructible, _Tp&>::value) { return __to_array(__a, make_index_sequence<_Nm>{}); } diff --git a/libstdc++-v3/testsuite/experimental/array/make_array.cc b/libstdc++-v3/testsuite/experimental/array/make_array.cc index 45b192037e6..1b7d60e3173 100644 --- a/libstdc++-v3/testsuite/experimental/array/make_array.cc +++ b/libstdc++-v3/testsuite/experimental/array/make_array.cc @@ -18,7 +18,6 @@ // . #include -#include struct MoveOnly { @@ -27,7 +26,7 @@ struct MoveOnly MoveOnly& operator=(MoveOnly&&) = default; }; -int main() +void test01() { char x[42]; std::array y = std::experimental::to_array(x); @@ -45,3 +44,13 @@ int main() = std::experimental::make_array(1,2L, 3); constexpr std::array zzz2 = std::experimental::make_array(MoveOnly{}); } + +void test02() +{ + // PR libstdc++/79195 + struct A {}; + struct B : A {}; + struct C : A {}; + auto arr = std::experimental::make_array(B{}, C{}); + static_assert(std::is_same>::value, ""); +} diff --git a/libstdc++-v3/testsuite/experimental/array/neg.cc b/libstdc++-v3/testsuite/experimental/array/neg.cc index 790933d4acf..3963287f257 100644 --- a/libstdc++-v3/testsuite/experimental/array/neg.cc +++ b/libstdc++-v3/testsuite/experimental/array/neg.cc @@ -24,5 +24,5 @@ int main() { int dummy; auto bad = std::experimental::make_array(std::ref(dummy)); - // { dg-error "make_array cannot be used without an explicit target type if any of the types given is a reference_wrapper" "" { target *-*-* } 76 } + // { dg-error "explicit target type" "" { target *-*-* } 78 } } -- 2.30.2