struct B
{
int a;
void foo() {a = 5;}
};
template <typename T>
struct A
{
A(int i) { B::foo(); }
A(double d) {}
};
int main()
{
A<int> a(5.0);
}
gcc 4.7.2 компилирует его без ошибок.
clang 3.4svn жалуется:
$ clang -Wall -Wextra test.cpp
test.cpp:10:16: error: call to non-static member function without an object argument
A(int i) { B::foo(); }
~~~^~~
Конечно, код неправильный, но какой компилятор соответствует стандарту?
Также странно, что clang не печатает никаких примечаний «в экземпляре», как это делает gcc, если вы используете 5 вместо 5.0:
$ gcc test.cpp
test.cpp: In instantiation of ‘A<T>::A(int) [with T = int]’:
test.cpp:15:12: required from here
test.cpp:9:13: error: cannot call member function ‘void B::foo()’ without object
Ваша программа неверна, и оба компилятора верны, поскольку стандарт не требует диагностики от соответствующего компилятора (что позволяет gcc игнорировать ее). Шаблон, для которого не может быть действительного экземпляра (специализация на стандартном жаргоне), является неправильным, даже если этот шаблон никогда не создавался.
В вашем случае имя B::foo()
внутри A<T>::A(int)
это независимое имя, поэтому оно должно быть разрешено во время поиска первой фазы, и оно может ссылаться только на B
класс, определенный выше. Потому что это не static
функция-член, но нестатическая, код неверный, независимо от типа T
используется для создания экземпляра A<T>
шаблон и программа плохо сформированы.
Соответствующая цитата из 14.6 [temp.res] / 8:
Знание того, какие имена являются именами типов, позволяет проверять синтаксис каждого определения шаблона. Не должно быть выдано никакой диагностики для определения шаблона, для которого может быть сформирована действительная специализация. Если для определения шаблона не может быть сгенерировано никакой действительной специализации, и этот шаблон не создан, определение шаблона неверно, диагностика не требуется.
Других решений пока нет …