6

In the following program struct B is parametrized by a non-type template argument with default value of a lambda object:

template <auto = []{}>
struct B {};

// ok everywhere
[[maybe_unused]] B<> b1, b2;
static_assert( std::is_same_v<decltype(b1), decltype(b2)> );

// ok in GCC only
[[maybe_unused]] B b3, b4;
static_assert( !std::is_same_v<decltype(b3), decltype(b4)> );

If two variables are declared as B<> b1, b2 then they both have the same type. But if one declares B b3, b4 then GCC makes them of distinct types (each with its own lambda). At the same time MSVC and Clang refuse to accept it. MSVC error:

<source>(11): error C3538: in a declarator-list 'B' must always deduce to the same type
<source>(11): note: could be 'B<<lambda_2_>{}>'
<source>(11): note: or       'B<<lambda_3_>{}>'

Clang error is more confusing:

error: template arguments deduced as 'B<{}>' in declaration of 'b3' and deduced as 'B<{}>' in declaration of 'b4'

Demo: https://gcc.godbolt.org/z/fcfW6a3es

Which compiler is right here?

Fedor
  • 17,146
  • 13
  • 40
  • 131
  • Feels that you try to sneak lambdas into template arguments, wasn't it prohibited by [expr.prim.lambda] paragraph 2 ? – Öö Tiib Jan 04 '22 at 21:53
  • 2
    Given https://timsong-cpp.github.io/cppwp/n4868/dcl.decl.general#3.sentence-1 and https://timsong-cpp.github.io/cppwp/n4868/dcl.type.class.deduct#1.sentence-3, Clang and MSVC are correct. It is the same as for `auto` type deduction https://timsong-cpp.github.io/cppwp/n4868/dcl.spec.auto.general#7 – Language Lawyer Jan 04 '22 at 21:54
  • @ÖöTiib It was changed in C++20 with http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0315r4.pdf. – user17732522 Jan 04 '22 at 22:17

0 Answers0