Bug 90533

Summary: [C++20] cannot redeclare telmplate function if it contains lambda expression in its declaration
Product: gcc Reporter: Mitsuru Kariya <kariya_mitsuru>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: webrown.cpp
Priority: P3 Keywords: c++-lambda
Version: 9.1.0   
Target Milestone: 14.0   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104548
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2022-02-16 00:00:00
Bug Depends on:    
Bug Blocks: 107430, 54367    

Description Mitsuru Kariya 2019-05-19 15:49:46 UTC
The sample code below should be compiled successfully in c++20 mode but gcc 9.1.0 or above generate compilation error.

=========================sample code=========================
template <int N> static void k(decltype([]{ return 0; }()));
template <int N> static void k(decltype([]{ return 0; }()));
template <int N> static void k(int) {}

int main()
{
    k<0>(0);
}
=======================compiler output=======================
prog.cc: In function 'int main()':
prog.cc:7:11: error: call of overloaded 'k<0>(int)' is ambiguous
    7 |     k<0>(0);
      |           ^
prog.cc:1:30: note: candidate: 'void k(decltype (<lambda>())) [with int N = 0; decltype (<lambda>()) = int]'
    1 | template <int N> static void k(decltype([]{ return 0; }()));
      |                              ^
prog.cc:2:30: note: candidate: 'void k(decltype (<lambda>())) [with int N = 0; decltype (<lambda>()) = int]'
    2 | template <int N> static void k(decltype([]{ return 0; }()));
      |                              ^
prog.cc:3:30: note: candidate: 'void k(int) [with int N = 0]'
    3 | template <int N> static void k(int) {}
      |                              ^
=============================================================
cf. https://wandbox.org/permlink/GRhyXXNttvOtlNxu

The 1st and 2nd declarations should not contain closure type in its signature because an operand of the decltype contains no template parameter.
So these three declarations should be identical.

Note that the sample code above is from p0315r4 and the paper says that it is equivalent to a following code that is compiled successfully by gcc 9.1.0 or above.
=========================sample code=========================
struct lambda { auto operator()() const { return 0; } };
template <int N> static void k(decltype(lambda{}()));
template <int N> static void k(decltype(lambda{}()));
template <int N> static void k(int) {}

int main()
{
    k<0>(0);
}
=======================compiler output=======================
cf. https://wandbox.org/permlink/jUosb2rfxR58JBbx

I think the code above is bit inaccurate but a more precise version below is also compiled successfully by gcc 9.1.0 or above.
=========================sample code=========================
struct lambda1 { auto operator()() const { return 0; } };
struct lambda2 { auto operator()() const { return 0; } };
template <int N> static void k(decltype(lambda1{}()));
template <int N> static void k(decltype(lambda2{}()));
template <int N> static void k(int) {}

int main()
{
    k<0>(0);
}
=======================compiler output=======================
cf. https://wandbox.org/permlink/kl8K4AHTPL5dL4rq


[links]
Wording for lambdas in unevaluated contexts
  http://wg21.link/p0315r4
C++2a Support in GCC
  https://gcc.gnu.org/projects/cxx-status.html#cxx2a
Comment 1 Andrew Pinski 2022-02-16 01:32:05 UTC
Confirmed.
Comment 2 Andrew Pinski 2024-04-13 07:34:37 UTC
Fixed on the trunk by the recent lambda template argument patches.