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

            Bug ID: 90533
           Summary: [C++20] cannot redeclare telmplate function if it
                    contains lambda expression in its declaration
           Product: gcc
           Version: 9.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kariya_mitsuru at hotmail dot com
  Target Milestone: ---

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

Reply via email to