On 16/06/2015 22:45, Jonathan Wakely wrote: > On 16/06/15 22:18 +0200, François Dumont wrote: >> On 12/06/2015 01:22, Jonathan Wakely wrote: >>> This fixes two test failures when the default compiler mode is >>> -std=gnu++14 >>> >>> FAIL: 25_algorithms/headers/algorithm/synopsis.cc (test for excess >>> errors) >>> FAIL: ext/profile/mutex_extensions_neg.cc (test for excess errors) >>> >>> I don't really like the change to the synopsis.cc test, but I don't >>> think reproducing the SFINAE constraints in the test is ideal either. >>> >>> The mutex_extensions_neg.cc test works now, but I think we're missing >>> specializations of __is_tuple_like_impl for __gnu_debug::array and >>> __gnu_profile::array. >>> >>> Tested powerpc64le-linux, committed to trunk. >>> >> This patch introduced a regression in >> 20_util/tuple/creation_functions/tuple_cat.cc in debug mode. > > Yes, I noticed this today while testing some changes to <debug/list>, > but hadn't had time to do anything about it, so thanks for taking care > of it. > >> Attached is a proposal to fix it properly. I am using <utility> as a >> pivot header between <tuple> and <array>. This way <tuple> do not need >> to include <array> anymore. > > I think that's a good improvement.
But it doesn't work. <array> needs to be included before tuple to make sure that constexpr involving array will work. So here is a less ambitious patch keeping <array> in <tuple>. What I don't understand is that when I try to remove <array> from <tuple> following code stop working: #include <tuple> #include <array> static_assert(std::is_same<decltype (std::tuple_cat(std::declval<std::array<int, 3>>())), std::tuple<int, int, int>>::value, "Error"); but if I invert <tuple> and <array> it does work. Now with <array> in <tuple> it works fine in any situation. However when I write: #include <tuple> #include <debug/array> static_assert(std::is_same<decltype (std::tuple_cat(std::declval<std::__debug::array<int, 3>>())), std::tuple<int, int, int>>::value, "Error"); it works too and I don't understand why ! * include/debug/array: Include normal array. Add version namespace when specializing tuple interface to array. Add specialization for __is_tuple_like_impl. * include/profile/array: Likewise. * include/std/array: Include <utility>. Add specialization for __is_tuple_like_impl. * include/std/tuple (__is_tuple_like_impl<>, __is_tuple_like_impl<pair>): Move... * include/std/utility: ... here. Include <type_traits>. Tested under Linux x86_64 normal and debug modes. Ok to commit ? François
diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array index 34e6281..a1c7d40 100644 --- a/libstdc++-v3/include/debug/array +++ b/libstdc++-v3/include/debug/array @@ -31,6 +31,8 @@ #pragma GCC system_header +#include <array> + #include <debug/formatter.h> #include <debug/macros.h> @@ -292,20 +294,27 @@ namespace __debug } } // namespace __debug +_GLIBCXX_BEGIN_NAMESPACE_VERSION // Tuple interface to class template array. /// tuple_size template<typename _Tp, std::size_t _Nm> - struct tuple_size<__debug::array<_Tp, _Nm>> + struct tuple_size<std::__debug::array<_Tp, _Nm>> : public integral_constant<std::size_t, _Nm> { }; /// tuple_element template<std::size_t _Int, typename _Tp, std::size_t _Nm> - struct tuple_element<_Int, __debug::array<_Tp, _Nm>> + struct tuple_element<_Int, std::__debug::array<_Tp, _Nm>> { static_assert(_Int < _Nm, "index is out of bounds"); typedef _Tp type; }; + + template<typename _Tp, std::size_t _Nm> + struct __is_tuple_like_impl<std::__debug::array<_Tp, _Nm>> : true_type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // _GLIBCXX_DEBUG_ARRAY diff --git a/libstdc++-v3/include/profile/array b/libstdc++-v3/include/profile/array index 434ca96..687c052 100644 --- a/libstdc++-v3/include/profile/array +++ b/libstdc++-v3/include/profile/array @@ -31,6 +31,8 @@ #pragma GCC system_header +#include <array> + namespace std _GLIBCXX_VISIBILITY(default) { namespace __profile @@ -253,20 +255,27 @@ namespace __profile } } // namespace __profile +_GLIBCXX_BEGIN_NAMESPACE_VERSION // Tuple interface to class template array. /// tuple_size template<typename _Tp, std::size_t _Nm> - struct tuple_size<__profile::array<_Tp, _Nm>> + struct tuple_size<std::__profile::array<_Tp, _Nm>> : public integral_constant<std::size_t, _Nm> { }; /// tuple_element template<std::size_t _Int, typename _Tp, std::size_t _Nm> - struct tuple_element<_Int, __profile::array<_Tp, _Nm>> + struct tuple_element<_Int, std::__profile::array<_Tp, _Nm>> { static_assert(_Int < _Nm, "index is out of bounds"); typedef _Tp type; }; + + template<typename _Tp, std::size_t _Nm> + struct __is_tuple_like_impl<std::__profile::array<_Tp, _Nm>> : true_type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // _GLIBCXX_PROFILE_ARRAY diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index 40fbd46..d1b5e6d 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -35,6 +35,7 @@ # include <bits/c++0x_warning.h> #else +#include <utility> #include <stdexcept> #include <bits/stl_algobase.h> #include <bits/range_access.h> @@ -331,6 +332,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Tp type; }; + template<typename _Tp, std::size_t _Nm> + struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type + { }; + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 953d16b..0504012 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -976,22 +976,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION forward_as_tuple(_Elements&&... __args) noexcept { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } - template<typename> - struct __is_tuple_like_impl : false_type - { }; - template<typename... _Tps> struct __is_tuple_like_impl<tuple<_Tps...>> : true_type { }; - template<typename _T1, typename _T2> - struct __is_tuple_like_impl<pair<_T1, _T2>> : true_type - { }; - - template<typename _Tp, std::size_t _Nm> - struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type - { }; - // Internal type trait that allows us to sfinae-protect tuple_cat. template<typename _Tp> struct __is_tuple_like diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 1aac77c..89b6852 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -71,6 +71,7 @@ #if __cplusplus >= 201103L +#include <type_traits> #include <bits/move.h> #include <initializer_list> @@ -84,7 +85,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<std::size_t _Int, class _Tp> class tuple_element; - // Various functions which give std::pair a tuple-like interface. + template<typename> + struct __is_tuple_like_impl : false_type + { }; + + // Various functions which give std::pair a tuple-like interface. + + /// Partial specialization for std::pair + template<typename _T1, typename _T2> + struct __is_tuple_like_impl<std::pair<_T1, _T2>> : true_type + { }; /// Partial specialization for std::pair template<class _Tp1, class _Tp2>