Repository navigation
Address of class-type NTTP in a member template signature fails deduction after enclosing template is instantiated #423
Description
Issue Summary
When a class-type non-type template parameter V is substituted as part of instantiating an enclosing template (a class template, a partial specialization, or a function template containing a generic lambda), and &V appears in the signature of a member function template together with a still-dependent parameter, deducing the member template's arguments fails.
The substituted expression refers to the template parameter object, and when it is rescanned during deduction, make_operand_for_rescanned_identifier (src/expr.c) only rebuilds the object as an lvalue if the object's initializer is associated with a constant symbol. Otherwise, it falls back to make_constant_operand, which turns V into a prvalue, so &V is ill-formed and deduction fails.
GCC 15 and Clang 21 accept the code below. This is independent of #414 / #422: it fails the same way with and without that change.
Reproducing Source Code
struct A { int i = 0; };
constexpr A a1{1};
template <A V> struct S {
template <typename T> static auto f(T t) -> decltype(t, &V);
};
using R1 = decltype(S<a1>::f(0));
template <A V> constexpr auto mk() {
return [](auto t) -> decltype(t, &V) { return &V; };
}
static_assert(mk<a1>()(0) == mk<a1>()(0L));
template <typename T, typename U> struct X;
template <A V> struct Tag { };
template <A V, typename U> struct X<Tag<V>, U> {
template <typename T> static auto f(T t) -> decltype(t, U(), &V);
};
using R3 = decltype(X<Tag<a1>, int>::f(0));Command-line Options
cpfe --c++20 test.cpp
Type of Issue
[Front End] This code SHOULD compile with these options.
Additional Details
Current output:
"test.cpp", line 7: error: no instance of function template
"S<V>::f [with V=A{1}]" matches the argument list
argument types are: (int)
using R1 = decltype(S<a1>::f(0));
^
"test.cpp", line 5: note: candidate function template "S<V>::f
[with V=A{1}]" failed deduction
template <typename T> static auto f(T t) -> decltype(t, &V);
^
"test.cpp", line 12: error: no instance of function template
"lambda [](auto)->decltype((<expression>))" matches the argument list
argument types are: (int)
object type is: lambda [](auto)->decltype((<expression>))
static_assert(mk<a1>()(0) == mk<a1>()(0L));
^
"test.cpp", line 10: note: candidate function template "lambda
[](auto)->decltype((<expression>))" failed deduction
return [](auto t) -> decltype(t, &V) { return &V; };
^
"test.cpp", line 12: error: no instance of function template
"lambda [](auto)->decltype((<expression>))" matches the argument list
argument types are: (long)
object type is: lambda [](auto)->decltype((<expression>))
static_assert(mk<a1>()(0) == mk<a1>()(0L));
^
"test.cpp", line 10: note: candidate function template "lambda
[](auto)->decltype((<expression>))" failed deduction
return [](auto t) -> decltype(t, &V) { return &V; };
^
"test.cpp", line 19: error: no instance of function template
"X<Tag<V>, U>::f [with V=A{1}, U=int]" matches the argument list
argument types are: (int)
using R3 = decltype(X<Tag<a1>, int>::f(0));
^
"test.cpp", line 17: note: candidate function template
"X<Tag<V>, U>::f [with V=A{1}, U=int]" failed deduction
template <typename T> static auto f(T t) -> decltype(t, U(), &V);
^
4 errors detected in the compilation of "test.cpp".
Expected: no errors. A quick experiment that makes the fallback in make_operand_for_rescanned_identifier produce a const lvalue for the template parameter object variable (instead of calling make_constant_operand) makes all three cases compile.
Reproducing (Standard) Configuration(s)
linux-gcc-debug
Activity