Почему не нужно ключевое слово шаблона, если существует несвязанная глобальная функция шаблона с таким же именем?
Этот вопрос связан с моим предыдущим вопросомОшибка компилятора при попытке вызвать метод шаблона из частного экземпляра, который был указан как связанный с этим вопросом:Где и почему я должен поставить ключевые слова "template" и "typename"?
Поэтому я прочитал это и понял, что определение языка C ++ неоднозначно, поэтому его не всегда можно правильно проанализировать. В моем случае ответ был таков, что мне нужноa.template f<1>()
вB::test()
чтобы помочь парсеру понять, что он имеет дело с шаблоном. Хорошо.
Но, прочитав все это, почему, черт возьми, парсер вдруг может обойтись безtemplate
ключевое слово, если у меня случится совершенно не связанная глобальная функция шаблона с таким же именем? Это компилируется без проблем и ведет себя как ожидалось:
#include <iostream>
template <int i>
void f() {std::cout << "f()\n";}
template <int N>
struct A {
template <int i>
void f() {std::cout << "A::f()\n";}
};
template <int N>
struct B {
A<N> a;
B(A<N>& a) : a(a) {}
void test() {
f<1>();
a.f<1>(); // compiles without 'template' keyword!
}
};
int main() {
A<2> a;
a.f<1>(); // works fine
B<2> b(a);
b.test();
}
Я обнаружил, что глобальная функция должна:
называтьсяf
быть функцией шаблонабыть определены доB
В противном случае, это может быть что угодно. Так
template <typename T, unsigned k>
void *f(double x, const char *s) {return NULL;}
работает так же хорошо, чтобы помочь парсеру, чтоa.f<1>()
вB::test()
фактически должен быть разобран какa.template f<1>()
.
О чем думает компилятор? Например: «Ну, у парня уже есть глобальная шаблонная функция под названиемf<>()
, поэтому, когда я анализирую это совершенно не связанное выражениеa.f<1>()
внутриB::test()
Я собираюсь предположить, что это также функция шаблона? "Что это?
Что я пропустил при чтенииГде и почему я должен поставить ключевые слова "template" и "typename"??
Обновить
Код выше компилируется для меня со всеми:
i686-apple-darwin11-llvm-g ++ - 4.2 (GCC) 4.2.1 (на основе Apple Inc., сборка 5658) (сборка LLVM 2336.9.00)Apple clang версии 3.1 (теги / Apple / clang-318.0.58) (на основе LLVM 3.1svn)g ++ - 4.8 (GCC) 4.8.2Я также проверил с флагами компилятора-pedantic -Wall -Wextra
и с-std=c++11
заg++-4.8
, Это работало во всех случаях.
Обновление 2
Это также работает безtemplate
ключевое слово:
// ...
template <int N, template <int> class A>
struct B {
A<N> a;
B(A<N>& a) : a(a) {}
void test() {
f<1>();
a.f<1>(); // compiles without 'template' keyword!
}
};
int main() {
A<2> a;
a.f<1>(); // works fine
B<2, A> b(a);
b.test();
}