The code below compiles fine with Clang trunk and does not compile with GCC trunk at the time of posting. An interesting phenomenon of note is the fact that the GCC error message has no diagnostics besides the fact that template argument deduction failed.
template<typename>
struct foo {
template<typename = decltype([]{})>
void bar() {}
};
int main() {
[[maybe_unused]] auto v = foo<void>();
v.bar<int>(); // OK
v.bar<decltype([]{})>(); // OK
// compiles if these two lines are commented out:
v.bar<>(); // deduction failure
v.bar(); // deduction failure
}
godbolt: https://godbolt.org/z/hrqcefvb8
Compiler output:
<source>: In function 'int main()':
<source>:15:12: error: no matching function for call to 'foo<void>::bar<>()'
15 | v.bar<>(); // deduction failure
| ~~~~~~~^~
<source>:4:10: note: candidate: 'template<class> void foo< <template-parameter-1-1> >::bar() [with <template-parameter-1-1> = void]'
4 | void bar() {}
| ^~~
<source>:4:10: note: template argument deduction/substitution failed:
<source>:16:10: error: no matching function for call to 'foo<void>::bar()'
16 | v.bar(); // deduction failure
| ~~~~~^~
<source>:4:10: note: candidate: 'template<class> void foo< <template-parameter-1-1> >::bar() [with <template-parameter-1-1> = void]'
4 | void bar() {}
| ^~~
<source>:4:10: note: template argument deduction/substitution failed:
Compiler returned: 1
But interestingly enough, the code below compiles on both compilers:
template<typename = decltype([]{})>
void foo() {}
int main() {
foo<>();
foo();
}
godbolt: https://godbolt.org/z/dbd7GTrqj
My question is why the first snippet does not compile on GCC if it is not a bug. While it is not the focus of this question, it would be nice to have the empty substitution failure message produced by GCC explained.
My rationalisation as to how the decltype(<stateless lambda expression>) default parameter might not be accepted as a default parameter is a combination of [defns.signature.templ]
including parameter-type-list
and "signature of the template-head
" combined with Note 4 in [temp.fct]
which clarifies that lambda types cannot appear in any "linked" symbols. This, however, is likely not the answer to why GCC does not compile as [defns.signature.template.head]
clearly excludes default arguments from the signature.
Yes, it's a confirmed bug in gcc.
There is a meta-bugreport, Bug 107430 (c++-lambda-decltype) - [meta-bug] lambda in decltype, which has this description:
I noticed there are many issues with lambda inside a
decltype
issues. Especially dealing with template alias.
It has a large collection of lambda/decltype
related bugs.
I opened a new one:
Bug 110604 - template argument deduction failed with decltype(lambda) containing your exact code and that bug report was linked as a duplicate of this confirmed bug:
Bug 93595 - [c++20] function call, substitution failure of template paramter with a lambda default in template context