On Thu, 13 Mar 2025 at 21:54, Jonathan Wakely <jwak...@redhat.com> wrote:
>
> On Thu, 13 Mar 2025 at 21:29, Patrick Palka <ppa...@redhat.com> wrote:
> >
> > On Thu, 13 Mar 2025, Ville Voutilainen wrote:
> >
> > > On Thu, 13 Mar 2025 at 23:16, Ville Voutilainen
> > > <ville.voutilai...@gmail.com> wrote:
> > > >
> > > > On Thu, 13 Mar 2025 at 23:03, Patrick Palka <ppa...@redhat.com> wrote:
> > > > > +      // Defined as a template to work around PR libstdc++/116440.
> > > > > +      template<class...>
> > > > > +       constexpr explicit(!__convertible<const _Elements&...>())
> > > > > +       tuple(const _Elements&... __elements)
> > > >
> > > > I don't understand how a constructor template declared like this can
> > > > ever be called. The template parameter pack
> > > > can't be provided or deduced, and can't have a default. So we're
> > > > effectively making this signature always lose
> > > > overload resolution to the one that takes a pack of _UElements&&.
> > > >
> > > > Which may be fine. I can't head-compile a test that would fail in that
> > > > case. If any of the incoming argument isn't one
> > > > of _Elements, that constructor wins overload resolution anyway. If the
> > > > incoming arguments are exactly _Elements, that
> > > > constructor does the same thing as this one. I think.
> > >
> > > Oh, never mind. The pack is just deduced as an empty pack.
> >
> > Yep that's my understanding, though I don't know where in the standard
> > this is specified, a quick Ctrl+F is failing me.
> >
> > I can use template<int = 0> or template<typename = void> if that's
> > preferred :)
>
> I would prefer template<typename = void> to the empty pack, I think
> the default template argument makes it a little more obvious how that
> constructor can be called (I'm sure Ville won't be the only one to
> raise an eyebrow at that).
>
> Thanks for figuring this out, and noticing that that the template-ness
> of that constructor is what changed between C++17 and C++20. I think
> when I re-implemented it using concepts I assumed the template-ness
> was there for the _ImplicitCtor / _ExplicitCtor stuff, which is done
> using explicit(bool) in C++20. I wasn't looking at the tuple(const
> _Elements&...) constructor at all, because the errors all pointed to
> tuple(_UTypes&&...).
>
> Do we also want to constraint the tuple(const _Elements&...)
> constructor with requires sizeof...(_Elements) >= 1, which is present
> on the C++17 version?

Oh we don't need that constraint, because we have an explicit
specialization for tuple<>.

Reply via email to