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)