Когда я пытаюсь скомпилировать этот код
// void foobar(int);
template <class T>
struct Foo {
void bar(T t) { foobar(t); };
};
void foobar(int);
template class Foo<int>;
с g++ 4.8.2 Появляется следующее сообщение об ошибке
foo.cc: In instantiation of ‘void Foo<T>::bar(T) [with T = int]’:
foo.cc:10:16: required from here
foo.cc:5:27: error: ‘foobar’ was not declared in this scope, and no
declarations were found by argument-dependent lookup at
the point of instantiation [-fpermissive]
void bar(T t) { foobar(t); };
^
foo.cc:8:6: note: ‘void foobar(int)’ declared here, later in the translation unit
void foobar(int);
^
(С clang 3.4 это почти то же самое).
Во-первых, я думаю, что код правильный и должен компилироваться, поскольку foobar является зависимым именем в объявлении шаблона и должен быть просмотрен только в фазе два при создании экземпляра шаблона. Когда это делается в последней строке, "foobar (int)" уже объявлен. Код компилируется, BTW, когда я раскомментирую самую верхнюю строку, но обе декларации до создания экземпляра, и поэтому это не имеет значения.
Во-вторых, само сообщение об ошибке кажется мне противоречивым. В нем говорится: "Никаких деклараций не было найдено в момент становления", то есть foo.cc:10:16, и он говорит, что он объявлен "позже" в foo.cc:8:6. Для всего, что я знаю о числах и английском языке, я бы назвал это "раньше", а не "позже".
Итак, это ошибка в gcc или у меня что-то не так? Так как это кажется мне общей моделью использования, я не могу поверить в это, однако.
Кстати: когда я тестирую второй пример "Разрешение имен для зависимых типов" в MSDN (http://msdn.microsoft.com/en-us/library/dx2zs2ee.aspx) с g++, результат отличается от vС++, который (не в общем, но в этом конкретном случае) подорвал бы это, будучи ошибкой в g++.