如果存在具有相同名称的不相关全局模板函数,为什么不需要模板关键字?

Ste*_*fan 7 c++ templates compiler-errors

此问题与我之前的问题有关,当尝试从私有实例调用模板方法时出现编译器错误,这被指出与此问题有关:我在哪里以及为什么要放置"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();
}
Run Code Online (Sandbox Code Playgroud)

我发现全局函数必须:

  • 叫做 f
  • 是一个模板功能
  • 以前定义 B

否则,它几乎可以是任何东西.所以

template <typename T, unsigned k>
void *f(double x, const char *s) {return NULL;}
Run Code Online (Sandbox Code Playgroud)

作品一样好,帮助解析器指出,a.f<1>()B::test()实际上是在被解析为a.template f<1>().

什么是编译器思考?像:"好了,这家伙已经有一个叫做全局模板功能f<>(),所以当我解析此完全无关的表情a.f<1>()B::test(),我会认为这也是一个模板函数?" 这是什么?

我在阅读时错过了什么?为什么我必须放置"模板"和"typename"关键字?

更新

上面的代码为我编译了所有:

  • i686-apple-darwin11-llvm-g ++ - 4.2(GCC)4.2.1(基于Apple Inc. build 5658)(LLVM build 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++11for 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();
}
Run Code Online (Sandbox Code Playgroud)

vso*_*tco 2

我认为g++是正确的,代码应该在没有.template. 根据标准(至少按照我的理解),

3.4.5/1(N3936 第 55 页)

在类成员访问表达式 (5.2.5) 中,如果 . 或 -> 标记后紧跟一个标识符,后跟一个 <,必须查找标识符以确定 < 是模板参数列表 (14.2) 的开头还是小于运算符。首先在对象表达式的类中查找标识符。如果未找到标识符,则在整个后缀表达式的上下文中查找它并命名一个类模板。

  • 那么,这是否意味着我的讽刺描述:“编译器在想什么?” 事实上到底是怎么回事?我的天啊。 (2认同)