https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122132
Bug ID: 122132
Summary: Template parameter default argument of pre-declared
nested classes not recognised if implementation has
constructor
Product: gcc
Version: 15.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: sandro.boehler at gmx dot de
Target Milestone: ---
Discovered with
gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 13.2.0
According to compiler explorer (godbolt) still present on trunk (at least for
both x86-x64 and ARM7 standard builds), though (clang included for comparison):
https://godbolt.org/z/n94E9nKes
In the following case the default argument for a pre-declared nested template
is not recognised:
struct wrapper
{
template <typename T = long>
struct nested;
};
template <typename T>
struct wrapper::nested
{
nested(int) { }
};
int main()
{
wrapper::nested n(7);
return 0;
}
Compiler error output (details omitted):
error: class template argument deduction failed:
18 | outer::inner t(7);
error: no matching function for call to 'inner(int)'
The error does NOT occur if the affected template class
* is not a nested class
* does not have a constructor unrelated to the template parameter
template <typename T>
struct wrapper::nested
{
// nested(int) { } // omitted!
};
template <typename T = long>
struct non_nested;
template <typename T = long>
struct non_nested
{
non_nested(int);
};
int main()
{
wrapper::nested n;
non_nested nn;
return 0;
}
Repeating the default template argument allows compilation:
struct wrapper
{
template <typename T = long>
struct nested;
};
template <typename T = long> // !!!
struct wrapper::nested
{
nested(int) { }
};
This does not conform to the standard, though, and actually should be rejected
just as in bug 50370 (opened in 2011, resolved in 2022):
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50370