Почему не нужно ключевое слово шаблона, если существует несвязанная глобальная функция шаблона с таким же именем?

Этот вопрос связан с моим предыдущим вопросомОшибка компилятора при попытке вызвать метод шаблона из частного экземпляра, который был указан как связанный с этим вопросом:Где и почему я должен поставить ключевые слова "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();
}

Ответы на вопрос(1)

Ваш ответ на вопрос