Почему эта небольшая программа на С++ не компилируется с использованием g++?

Следующий код не будет компилироваться с помощью g++ 4.5 или 4.6 (моментальный снимок). Он будет компилироваться с помощью компилятора Digital Mars 8.42n.

template <int I>
struct Foo {
  template <int J>
  void bar(int x) {}
};

template <int I>
void test()
{
  Foo<I> a;
  a.bar<8>(9);
};

int main(int argc, char *argv[]) {
  test<0>();
  return 0;
}

Сообщение об ошибке:

bugbody.cpp: In function 'void test() [with int I = 0]':
bugbody.cpp:16:11:   instantiated from here
bugbody.cpp:11:3: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'

Является ли программа действительной С++?

Ответ 1

Так как bar in a.bar является зависимым именем, компилятор не знает, что его шаблон. Вы должны указать это, иначе компилятор интерпретирует последующие <…> как операторы двоичного сравнения:

a.template bar<8>(9);

Компилятор ведет себя корректно.

Причина такого поведения заключается в специализации. Представьте, что вы специализировали класс Foo для некоторого значения:

template <>
struct Foo<0> {
    int bar;
};

Теперь ваш исходный код будет компилироваться, но это будет означать что-то совершенно другое. В первом сеансе синтаксического анализа компилятор еще не знает, какая специализация Foo используется здесь, поэтому ему необходимо устранить двусмысленность между двумя возможными способами использования a.bar; следовательно, ключевое слово template, чтобы показать компилятору, что последующие <…> являются аргументами шаблона.