如果存在具有相同名称的不相关的全局模板函数,为什么不需要模板关键字? [英] Why is no template keyword needed if an unrelated global template function with same name exists?

查看:109
本文介绍了如果存在具有相同名称的不相关的全局模板函数,为什么不需要模板关键字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题与我之前的问题有关尝试从私有实例调用模板方法时出现编译器错误,这被指出与此问题相关:在哪里和为什么我必须将模板和类型名称关键字?



所以我读这个,我得到的想法,C ++语言定义是不明确的,所以它不能总是正确解析。在我的case,答案是,我需要 a.template f< 1>() B :: test()来帮助解析器理解它正在处理一个模板。但是,在阅读所有这些之后,为什么heck是解析器突然能够做没有模板



<关键字如果我碰巧有一个完全不相关的全局模板函数碰巧有相同的名称?此编译没有问题,并按预期运行:

  #include< iostream> 

template< int i>
void f(){std :: cout<< f()\\\
;}

template< int N>
struct A {
template< int i>
void f(){std :: cout<< A :: f()\\\
;}
};

模板< int N>
struct B {
A&一个;

B(A& a):a(a){}

void test(){
f
a.f< 1>(); //编译没有'template'关键字!
}
};

int main(){
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;}

也可以帮助解析器在 B :: test() a.f <1>() >实际上被解析为 a.template f <1>()



思维?喜欢:嗯,这家伙已经有一个全局模板函数 f<>(),所以当我解析这个完全不相关的表达式 a.f 1()里面 B :: test(),我想假设它也是一个模板函数?这是什么?



在阅读

我有以下所有:




  • i686-apple-darwin11-llvm-g ++ - 4.2(GCC)4.2.1构建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 for g ++ - 4.8



这也适用于没有 code> template 关键字:

  // ... 
template< ; int N,template< int> A类>
struct B {
A&一个;

B(A& a):a(a){}

void test(){
f
a.f< 1>(); //编译没有'template'关键字!
}
};

int main(){
A&一个;
a.f< 1>(); // works fine
B< 2,A> b(a);
b.test();
}


解决方案

c> g ++ 是正确的,代码应该编译没有 .template 。根据标准(至少根据我的理解),



3.4.5 / 1 (N3936第55页)



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


This question is related to my previous question Compiler error when trying to call template method from private instance, which was pointed out to be related to this question: Where and why do I have to put the "template" and "typename" keywords?

So I read this and I get the idea that the C++ language definition is ambiguous so it cannot always be parsed correctly. In my case, the answer was that I need a.template f<1>() in B::test() to help the parser understand that it is dealing with a template. Fine.

But, after reading all this, why the heck is the parser suddenly able to do without the template keyword if I happen to have a completely unrelated global template function that happens to have the same name? This compiles without problems and behaves as expected:

#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();
}

I found that the global function must:

  • be called f
  • be a template function
  • be defined before B

Otherwise, it can be pretty much anything. So

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

works just as well to help the parser out that a.f<1>() in B::test() is in fact to be parsed as a.template f<1>().

What is the compiler thinking? Like: "Well, the guy already has a global template function called f<>(), so when I'm parsing this completely unrelated expression a.f<1>() inside B::test(), I'm going to assume that it's also a template function?" What is this?

What did I miss when reading Where and why do I have to put the "template" and "typename" keywords??

Update

The code above compiles for me with all of:

  • i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00)
  • Apple clang version 3.1 (tags/Apple/clang-318.0.58) (based on LLVM 3.1svn)
  • g++-4.8 (GCC) 4.8.2

I also tested with the compiler flags -pedantic -Wall -Wextra and with -std=c++11 for g++-4.8. It worked in all cases.

Update 2

This also works without template keyword:

// ...
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();
}

解决方案

I think g++ is correct and the code should compile without .template. According to the standard (at least up to my understanding),

3.4.5/1 (page 55 of N3936)

In a class member access expression (5.2.5), if the . or -> token is immediately followed by an identifier followed by a <, the identifier must be looked up to determine whether the < is the beginning of a template argument list (14.2) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template.

这篇关于如果存在具有相同名称的不相关的全局模板函数,为什么不需要模板关键字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆