https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127373

            Bug ID: 127373
           Summary: ICE when instantiating conversion to pointer to
                    function for generic lambda
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: sugrob9000aero at gmail dot com
  Target Milestone: ---

The following example:

#include <concepts>
float(*pfn)() = []<std::integral I>()->I { return 0; };

causes ICE on gcc 16.2.1 and gcc 17.0.0 (probably earlier versions too),
during the instantiation of the pfn conversion in closure class.

I assume the reason is that gcc does not apply constraints (requires
clauses/concepts) to the conversion function template; and I assume
the right fix is to apply them. That would also fix:

#include <concepts>
struct foo: decltype([]<std::integral I>()->I { return 0; }),
            decltype([]<std::floating_point F>()->F { return 1; }) {};
constexpr float(*pfn)() = foo{};
static_assert(pfn() == 1);

which IMO is reasonable to accept, but GCC thinks the conversion in
pfn's initialization is ambiguous.

Previous discussion/report:
  https://gcc.gnu.org/pipermail/gcc/2026-September/248880.html
  https://gcc.gnu.org/pipermail/gcc/2026-September/248881.html

...

The standard says [expr.prim.lambda.closure#12]:

  For a generic lambda with no lambda-capture and no explicit object
  parameter ([dcl.fct]), the closure type has a conversion function
  template to pointer to function. The conversion function template
  has the same invented template parameter list, and the pointer to
  function has the same parameter types, as the function call operator
  template. The return type of the pointer to function shall behave as
  if it were a decltype-specifier denoting the return type of the
  corresponding function call operator template specialization.

That is, it says nothing specific about this. Should the instantiation
of conversion fail due to instantiation failure for operator() within
the decltype? Maybe, but forcing the decltype there at all needlessly
restricts type deduction. Currently the following is accepted by gcc:

int(*pfn)() = []<typename T>()->T { return {}; };

and IMO it's useful and should stay that way; but wedging a decltype
between T and pfn would break deduction. So I think the standard is
wrong here anyway and this part of it should be substantially fixed.

...

Clang seems to already do what I propose as a fix (propagating the
constraints to both call and conversion operators), and I found it to
"do the right thing" in all of the above examples:

  Example 1 is rejected with a good message (rather than gcc's ICE)
  Example 2 is accepted (rather than gcc's ambiguity)
  Example 3 is accepted (in agreement with gcc)

Reply via email to