Ответ 1
gcc
правильный; ваш фрагмент плохо сформирован!
// reduced testcase
template<class T>
class A { };
int main () {
A<float>::A<int> x; // ill-formed, bug in `clang` and `icc`
}
В приведенном выше тестовом сценарии мы имеем спецификатор вложенных имен, A<float>::
, за которым следует неквалифицированный идентификатор A
, за которым следует некоторая тарабарщина (<int>
).
Это связано с тем, что контекст, в котором появляется спецификатор вложенных имен, указывает, что во время поиска включаются имена функций (это означает, что сначала найден конструктор, а выражение плохо сформировано).
Релевантные отчеты об ошибках:
Как обойти "проблему"?
Существуют контексты, в которых имена участников, которые просматриваются через спецификатор вложенных имен (который назначает класс), не должны включать функции (следовательно, контексты, в которых конструктор не найден), ниже приведены несколько примеров:
template<class T>
struct A {
typedef T value_type;
};
struct A<float>::A<int> x; // ok, context: elaborate-type-specifier
typename A<float>::A<int> (); // ok, context: [expr.type.conv]p1
A<float>::A::value_type x; // ok, context: nested-name-specifier
struct X : A<float>::A<int> { }; // ok, context: base-specifier
Что говорит стандарт?
3.4.3.1p2
Члены класса[class.qual]
В поиске, в котором имена функций не игнорируются 88 а спецификатор вложенных имен назначает класс C:
- если имя, указанное после вложенного имени-спецификатора, при поиске на C, представляет собой введенное имя класса C (раздел 9) или
- в декларации using (7.3.3), которая является объявлением-членом, если имя, указанное после спецификатора вложенных имен, совпадает с идентификатором или именем шаблона-шаблона в последнем компонент * вложенного имени-спецификатора,
вместо этого имя считается именем конструктора класса C.
[Примечание:...]
Такое имя конструктора должно использоваться только в объявлении-id объявления, которое называет конструктор или декларацию использования.
88. Поиск, в котором игнорируются имена функций, включают имена, появляющиеся в вложенном имени-спецификаторе, специфицированный тип-спецификатор или базовый-спецификатор.
14.6.1p2
Локально объявленные имена[temp.local]
Подобно обычным (не шаблонным) классам, шаблоны классов имеют имя с введенным классом (Пункт 9). Имя введенного класса может использоваться как имя шаблона или Имя-типа.
Когда он используется с шаблоном-аргументом-списком, как шаблон-аргумент для шаблона-шаблона шаблона или как окончательный идентификатор в специфицированном спецификаторе типа шаблона класса друга декларации, это относится к самому шаблону класса.
В противном случае, это эквивалентно имени шаблона, за которым следуют шаблонные параметры шаблон класса, заключенный в
<>
.