[committed] libstdc++: std::make_signed_t<cv bool> should be ill-formed
Jonathan Wakely
jwakely@redhat.com
Mon Oct 10 14:05:16 GMT 2022
On Mon, 10 Oct 2022 at 14:50, Tim Song via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> On Mon, Oct 10, 2022 at 8:09 AM Patrick Palka via Libstdc++
> <libstdc++@gcc.gnu.org> wrote:
> >
> > On Mon, 10 Oct 2022, Jonathan Wakely via Libstdc++ wrote:
> >
> > > Tested powerpc64le-linux. Pushed to trunk.
> > >
> > > -- >8 --
> > >
> > > Currently we only reject std::make_signed_t<bool> but not cv bool.
> > > Similarly for std::make_unsigned_t<cv bool>.
> > >
> > > As well as making those ill-formed, this adds a requires-clause to the
> > > make_signed and make_unsigned primary templates. This makes
> > > non-integral, non-enum cases fail immediately with a clear error, rather
> > > than giving an error about __make_signed_selector<T, false, false> being
> > > incomplete.
> >
> > IIUC the requires-clause turns what was once a hard error into a SFINAE
> > error, so e.g. for
> >
> > template<class T> typename make_signed<T>::type f(int);
> > template<class T> void f(...);
> > int main() { f<void>(0); }
> >
> > the call to f would previously be rejected due to an error outside the
> > immediate context about incomplete __make_signed_selector, and now with
> > the requires-clause resolves to the second overload. I wonder if this
> > new behavior is conforming -- the examples in [structure.specifications]
> > of how to implement 'Mandates' suggest that a failed 'Mandates' should
> > yield a hard error?
>
> I'm also concerned about the inability to name make_signed<X> in a
> context that doesn't require its instantiation (e.g.,
> conditional_t<is_integral_v<T>, make_signed<T>,
> type_identity<T>>::type). That seems a plausible use case, and
> breaking it doesn't seem great to me (conformance aside).
Ah yes, that's a problem.
We could fix it like this:
template<typename _Tp>
struct make_unsigned;
template<typename _Tp>
#if __cpp_concepts
requires is_integral<_Tp>::value || __is_enum(_Tp)
struct make_unsigned<_Tp>
#else
struct make_unsigned
#endif
{ typedef typename __make_unsigned_selector<_Tp>::__type type; };
But that doesn't really improve the diagnostic much. It's simpler
just to revert the addition of the constraints.
More information about the Libstdc++
mailing list