G CC неправильно; struct A
является шаблонной сущностью , но явно не является шаблоном (так как оно не начинается с ключевого слова template
), поэтому нет никакой двусмысленности.
Чтобы подтвердить, мы можем переименовать параметр типа, чтобы увидеть, что G ++ пытается использовать перегрузку шаблона-шаблона.
template <typename X>
bool test() {
return true;
}
template <template <typename...> class Y>
bool test() {
return false;
}
template <typename U>
bool templfun() {
struct A {
bool f() {
return test<A>(); // <-- this gives an error
}
};
return test<A>(); // <-- this is ok
}
bool run() {
return templfun<int>();
}
Вывод G ++: ( ссылка на godbolt )
<source>:15:27: error: call of overloaded 'test<templfun() [with U = int]::A>()' is ambiguous
15 | return test<A>(); // <-- this gives an error
| ~~~~~~~^~
<source>:2:6: note: candidate: 'bool test() [with X = templfun() [with U = int]::A]'
2 | bool test() {
| ^~~~
<source>:7:6: note: candidate: 'bool test() [with Y = templfun()::A]'
7 | bool test() {
| ^~~~
Очевидно, что "candidate: 'bool test() [with Y = templfun()::A]'
" является поддельным.
Обратите внимание, что локальные типы не были разрешены в качестве аргументов шаблона до C ++ 11 (см. C ++ 03 § 14.3.1.2), чтобы можно было объяснить сложность реализации G ++.