The additional logic added to __is_convertible_helper in order to support is_nothrow_convertible makes some uses of is_convertible ill-formed. This appears to be due to PR c++/87603, but can be avoided just by defining a separate helper for is_nothrow_convertible. The same problems are likely to still exist for is_nothrow_convertible, but that is new and so won't cause regressions for existing users of is_convertible.
PR libstdc++/89194 * include/std/type_traits (__is_convertible_helper) (__is_convertible_helper<_From, _To, false>): Revert changes to support is_nothrow_convertible. (__is_nt_convertible_helper): New helper. (is_nothrow_convertible): Use __is_nt_convertible_helper. Tested powerpc64le-linux, committed to trunk.
commit 0fd1d35fad359e5406deb936688e228f96447ee9 Author: Jonathan Wakely <jwak...@redhat.com> Date: Tue Feb 5 15:16:09 2019 +0000 PR libstdc++/89194 untangle is_convertible and is_nothrow_convertible The additional logic added to __is_convertible_helper in order to support is_nothrow_convertible makes some uses of is_convertible ill-formed. This appears to be due to PR c++/87603, but can be avoided just by defining a separate helper for is_nothrow_convertible. The same problems are likely to still exist for is_nothrow_convertible, but that is new and so won't cause regressions for existing users of is_convertible. PR libstdc++/89194 * include/std/type_traits (__is_convertible_helper) (__is_convertible_helper<_From, _To, false>): Revert changes to support is_nothrow_convertible. (__is_nt_convertible_helper): New helper. (is_nothrow_convertible): Use __is_nt_convertible_helper. diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 7c7aeeb3b32..f05a583cb04 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -1344,9 +1344,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __is_convertible_helper { typedef typename is_void<_To>::type type; -#if __cplusplus > 201703L - typedef type __is_nothrow_type; -#endif }; template<typename _From, typename _To> @@ -1364,23 +1361,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static false_type __test(...); -#if __cplusplus > 201703L - template<typename _From1, typename _To1, - bool _NoEx = noexcept(__test_aux<_To1>(std::declval<_From1>()))> - static __bool_constant<_NoEx> - __test_nothrow(int); - - template<typename, typename> - static false_type - __test_nothrow(...); -#endif - public: typedef decltype(__test<_From, _To>(0)) type; - -#if __cplusplus > 201703L - typedef decltype(__test_nothrow<_From, _To>(0)) __is_nothrow_type; -#endif }; @@ -1391,10 +1373,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; #if __cplusplus > 201703L + template<typename _From, typename _To, + bool = __or_<is_void<_From>, is_function<_To>, + is_array<_To>>::value> + struct __is_nt_convertible_helper + : is_void<_To> + { }; + + template<typename _From, typename _To> + class __is_nt_convertible_helper<_From, _To, false> + { + template<typename _To1> + static void __test_aux(_To1) noexcept; + + template<typename _From1, typename _To1> + static bool_constant<noexcept(__test_aux<_To1>(std::declval<_From1>()))> + __test(int); + + template<typename, typename> + static false_type + __test(...); + + public: + using type = decltype(__test<_From, _To>(0)); + }; + /// is_nothrow_convertible template<typename _From, typename _To> struct is_nothrow_convertible - : public __is_convertible_helper<_From, _To>::__is_nothrow_type + : public __is_nt_convertible_helper<_From, _To>::type { }; /// is_nothrow_convertible_v