Bug 100091 - [11 Regression] decltype([]{}) rejected as a default template parameter
Summary: [11 Regression] decltype([]{}) rejected as a default template parameter
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 11.0
: P1 normal
Target Milestone: 11.0
Assignee: Jason Merrill
URL:
Keywords: rejects-valid
Depends on: 99478
Blocks:
  Show dependency treegraph
 
Reported: 2021-04-15 07:05 UTC by Pilar Latiesa
Modified: 2021-04-15 16:56 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 10.2.0, 10.3.0
Known to fail:
Last reconfirmed: 2021-04-15 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pilar Latiesa 2021-04-15 07:05:49 UTC
This piece of code is accepted by 10.2, but rejected by yesterday's (20210414) snapshot:

$ cat test.cpp

  template<typename = decltype([]{})>
  void f() {}

$ ../GCC-11/bin/g++ -std=c++20 -c test.cpp

test.cpp:2:30: error: lambda-expression in template parameter type
    2 | template<typename = decltype([]{})>
      |

It's a recent change in behaviour. Possibly caused by r11-8166-ge1666ebd9ad31dbd8b9b933c883bdd882cfd1522.

I'm labeling this as rejects-valid because I believe [basic.def.odr]/14 allows such an use of a lambda, but I hardly understand that wording.
Comment 1 Richard Biener 2021-04-15 08:21:32 UTC
Confirmed.
Comment 2 Martin Liška 2021-04-15 11:50:45 UTC
> It's a recent change in behaviour. Possibly caused by
> r11-8166-ge1666ebd9ad31dbd8b9b933c883bdd882cfd1522.

I can confirm that.
Comment 3 Richard Biener 2021-04-15 12:33:30 UTC
Of course such use of a lambda is quite pointless which in turn makes the P1 classification a bit odd (but given it's a new regression it's technically correct).  We'll be happy to demote this to P2 though.
Comment 4 Pilar Latiesa 2021-04-15 13:32:32 UTC
> Of course such use of a lambda is quite pointless 

Not as pointless as it might appear. This defaulted template parameter enables a form of stateful metaprogramming:

#include <type_traits>

template<typename, typename = decltype([]{})>
class T {};

static_assert(!std::is_same_v<T<int>, T<int>>); // passes with GCC 10

I don’t know if that is valid C++, and would love to know whether or not it is.

On the other hand, sometimes it is convenient to use lambdas this way:

template<typename TOp = decltype([](double x) { return x * x; })>
class my_functor
{
  [[no_unique_address]] TOp const Op = {};
};
Comment 5 Jason Merrill 2021-04-15 16:56:55 UTC
Fixed in r11-8199