https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94197
Bug ID: 94197 Summary: __is_constructible gives an access error Product: gcc Version: 10.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- This fails to compile, but I think should be valid: template<typename _Tp, typename _Up = _Tp&&> _Up __declval(int); template<typename _Tp> _Tp __declval(long); template<typename _Tp> auto declval() noexcept -> decltype(__declval<_Tp>(0)); template<bool B> struct bool_constant { static constexpr bool value = B; using type = bool_constant; }; using true_type = bool_constant<true>; using false_type = bool_constant<false>; template<typename...> using __void_t = void; template<typename _Tp, typename = void> struct __is_referenceable : public false_type { }; template<typename _Tp> struct __is_referenceable<_Tp, __void_t<_Tp&>> : public true_type { }; template<bool, typename _Tp, typename... _Args> struct __is_nt_constructible_impl : public false_type { }; template<typename _Tp, typename... _Args> struct __is_nt_constructible_impl<true, _Tp, _Args...> : public bool_constant<noexcept(_Tp(declval<_Args>()...))> { }; template<typename _Tp, typename _Arg> struct __is_nt_constructible_impl<true, _Tp, _Arg> : public bool_constant<noexcept(static_cast<_Tp>(declval<_Arg>()))> { }; template<typename _Tp> struct __is_nt_constructible_impl<true, _Tp> : public bool_constant<noexcept(_Tp())> { }; template<typename _Tp, typename... _Args> using __is_nothrow_constructible_impl = __is_nt_constructible_impl<__is_constructible(_Tp, _Args...), _Tp, _Args...>; /// is_nothrow_constructible template<typename _Tp, typename... _Args> struct is_nothrow_constructible : public __is_nothrow_constructible_impl<_Tp, _Args...>::type { }; /// is_nothrow_default_constructible template<typename _Tp> struct is_nothrow_default_constructible : public __is_nothrow_constructible_impl<_Tp>::type { }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_nothrow_copy_constructible_impl; template<typename _Tp> struct __is_nothrow_copy_constructible_impl<_Tp, false> : public false_type { }; template<typename _Tp> struct __is_nothrow_copy_constructible_impl<_Tp, true> : public __is_nothrow_constructible_impl<_Tp, const _Tp&> { }; /// is_nothrow_copy_constructible template<typename _Tp> struct is_nothrow_copy_constructible : public __is_nothrow_copy_constructible_impl<_Tp>::type { }; struct NType { NType(int); ~NType(); int i; private: NType(const NType&); NType& operator=(const NType&); int i2; }; static_assert( !is_nothrow_copy_constructible<NType>::value, "" ); cons.cc: In substitution of 'template<class _Tp, class ... _Args> using __is_nothrow_constructible_impl = __is_nt_constructible_impl<__is_constructible(_Tp), _Tp, _Args ...> [with _Tp = NType; _Args = {const NType&}]': cons.cc:84:12: required from 'struct __is_nothrow_copy_constructible_impl<NType, true>' cons.cc:90:12: required from 'struct is_nothrow_copy_constructible<NType>' cons.cc:106:53: required from here cons.cc:59:36: error: 'NType::NType(const NType&)' is private within this context 59 | = __is_nt_constructible_impl<__is_constructible(_Tp, _Args...), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cons.cc:101:3: note: declared private here 101 | NType(const NType&); | ^~~~~ cons.cc: In instantiation of 'struct __is_nt_constructible_impl<true, NType, const NType&>': cons.cc:84:12: required from 'struct __is_nothrow_copy_constructible_impl<NType, true>' cons.cc:90:12: required from 'struct is_nothrow_copy_constructible<NType>' cons.cc:106:53: required from here cons.cc:49:37: error: 'NType::NType(const NType&)' is private within this context 49 | : public bool_constant<noexcept(static_cast<_Tp>(declval<_Arg>()))> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cons.cc:101:3: note: declared private here 101 | NType(const NType&); | ^~~~~ The __is_constructible expression should evaluate to false, without giving an error. If the testcase is modified like this, it works: --- cons.cc~ 2020-03-16 16:06:11.415546445 +0000 +++ cons.cc 2020-03-16 16:06:13.419555634 +0000 @@ -81,13 +81,13 @@ template<typename _Tp> struct __is_nothrow_copy_constructible_impl<_Tp, true> - : public __is_nothrow_constructible_impl<_Tp, const _Tp&> + : public __is_nothrow_constructible_impl<_Tp, const _Tp&>::type { }; /// is_nothrow_copy_constructible template<typename _Tp> struct is_nothrow_copy_constructible - : public __is_nothrow_copy_constructible_impl<_Tp>::type + : public __is_nothrow_copy_constructible_impl<_Tp> { }; This doesn't make any sense to me.