On Thu, Feb 12, 2026 at 10:35 PM Patrick Palka <[email protected]> wrote:
> On Thu, Feb 12, 2026 at 4:23 PM Tomasz Kaminski <[email protected]> > wrote: > > > > > > > > On Thu, Feb 12, 2026 at 9:04 PM Ville Voutilainen < > [email protected]> wrote: > >> > >> On Thu, 12 Feb 2026 at 21:52, Jonathan Wakely <[email protected]> > wrote: > >> > > >> > This is similar to the r16-3536-g0bb0d1d2880d56 change for std::pair, > so > >> > that CTAD ignores the tuple(const Types&...) constructor and only uses > >> > the tuple(Types...) -> tuple<Types...> deduction guide. This ensures > >> > that the deduced type comes from the decayed argument types. > >> > > >> > libstdc++-v3/ChangeLog: > >> > > >> > PR libstdc++/121771 > >> > * include/std/tuple (tuple::tuple(const Elements&...)): Use > >> > type_identity_t to prevent constructor being used for CTAD. > >> > (tuple::tuple(allocator_arg_t, const A&, const Elements&...)): > >> > Likewise. > >> > * testsuite/20_util/tuple/cons/121771.cc: New test. > >> > --- > >> > > >> > Tested aarch64-linux. > >> > >> FWIW, LGTM. > > > > OK to merge it now, but I believe this is bug in GCC and we should open > an issue for it. > > The generated deduction guides are equivalent to: > > template<typename... Args> > > void foo(const Args&...); > > template<typename... Args> > > void foo(Args...); > > > > And for such overload, the call foo(bar) where bar is function is > ambiguous > > (https://godbolt.org/z/f96Mb5E1n), so they should get disambiguated by: > > https://eel.is/c++draft/over.match#best.general-2.11 > > > F1 is generated from a deduction-guide ([over.match.class.deduct]) and > F2 is not, or, if not that, > We don't get that far, we hit a hard error when checking constraints > on the implicit guide because they're in terms of class-scope helpers > so we need to instantiate an ill-formed tuple specialization. > > There's more info in the corresponding std::pair bug: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110853 > > Ah, the constructor uses: template<typename... _UTypes> static consteval bool __constructible() { if constexpr (sizeof...(_UTypes) == sizeof...(_Elements)) return __and_v<is_constructible<_Elements, _UTypes>...>; else return false; } That is a member of the tuple, so we deduce the arguments, and want to check tuple<_Elements...>::constructible(), which does instantiate it with deduced arguments. So we brought the problem on ourselves by declaring the funciton used as constraints as a member of the tuple. So, no bug in GCC, and this seems to be the correct fix. We should have language feature that would enable opting out of implicit CTAD.
