编译器将如何检查未实例化的模板代码? [英] What does a compiler check for uninstantiated template code?

查看:129
本文介绍了编译器将如何检查未实例化的模板代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,以下代码段使用gcc-4.9和clang-602编译

For example, the following code piece compiles with gcc-4.9 and clang-602

class Base                                                                      
{                                                                               
public:                                                                         
    static void foo() {}                                                        
    void badfoo(int i) {}                                                       
};                                                                              

template <typename T>                                                           
class Derived : public Base                                                     
{                                                                               
public:                                                                         
    void bar() { Base::foo(); }                                                 
    void badbar() { Base::badfoo(); }  // compiles ok
    //static void badbar() { Base::badfoo(); }  // compile error                                                                                    
    //void worsebar() { Base::nonexist(); }  // compile error                                   
};                                                                              

int main()                                                                      
{                                                                               
    return 0;                                                                   
}  

但是注释掉的行将无法编译.

But the commented out lines won't compile.

我的问题是:

  1. 为什么badbar()可以编译但worsebar()不可以编译?

  1. Why badbar() compiles but worsebar() doesn't ?

如果将badbar()更改为静态,则无论base::badfoo是否为静态,它都不会编译.

If I change badbar() to static it won't compile either, regardless if base::badfoo is static or not.

标准是否对在这种情况下应检查的内容有任何规定? gcc4.4实际上甚至拒绝编译badbar().

Does the standard say anything about what should be checked in this situation ? gcc4.4 actually refuses to compile even badbar().

更新:

问题1的答案很多,但是似乎编译器有时还要花很多精力检查重载,它恰好在gcc 4.4.3和4.8.2上出现,而在4.7.2和4.9.1上却没有.

Problem 1 has been explained by a number of answers, but it seems compilers sometimes go the extra mile to check overload as well, it happens to gcc 4.4.3 and 4.8.2, but not 4.7.2 and 4.9.1.

问题2:正如Marco A.指出的那样,clang无法编译,但gcc4.9仍然可以通过.但是,gcc4.2和gcc4.4都拒绝该代码,并且他们抱怨的错误是无匹配函数",而不是用clang调用没有对象的非静态成员".这个问题似乎没有定论答案,因此我要添加丹尼尔·弗雷(Daniel Frey)建议的语言律师标签.

Problem 2: As Marco A. pointed out, clang won't compile but gcc4.9 will still pass. However, gcc4.2 and gcc4.4 both reject the code, and the error they are complaining is "no matching function" rather than "calling non-static member without an object" in clang. There's seems to be no conclusive answer to this question, so I'm adding a language-lawyer tag as Daniel Frey suggested.

更多更新:

我认为问题2的答案现在非常清楚:由编译器决定是否添加静态声明会改变诊断.随编译器的不同以及同一编译器的不同版本而有所不同.语言律师没有露面,我将接受丹尼尔·弗雷(Daniel Frey)的回答,因为它最好地解释了第一个问题.但是,Marco A.和Hadi Brais的答案也值得一读.

I think for question 2 the answer is pretty clear now: it's up to the compiler whether adding static declaration will change the diagnosis. It varies from compiler to compiler and different versions of the same compiler. The language lawyer didn't show up, I'm going to accept Daniel Frey's answer as it best explained the first question. But answers from Marco A. and Hadi Brais also worth reading.

推荐答案

该标准仅要求在第一次解析模板时在第一阶段进行名称查找.这会在badbar中出现badfoo,这就是代码编译的原因.当时不需要编译器执行重载解析.

The standard only requires the name-lookup to happen at phase 1, when the template is first parsed. This turns up badfoo in badbar which is why the code compiles. The compiler is not required to do the overload resolution at that time.

实例化badbar时,然后在阶段2中执行过载解析(通常在名称查找后在之后的单独步骤发生)-在您的示例中不是这种情况.该原理可以在

The overload resolution (which always happens as a separate step after the name lookup) is then performed in phase 2 when badbar is instantiated - which is not the case in your example. This principle can be found in

3.4名称查找[basic.lookup]

1 名称查找规则统一适用于所有名称(包括 typedef-names (7.1.3), namespace-names (7.3 )和类名(9.1))所在的地方,只要语法允许在特定规则讨论的上下文中使用此类名称.名称查找将名称的使用与该名称的声明(3.1)相关联.名称查找应找到明确的名称声明(参见10.2).如果名称查找发现名称是函数名称,则名称查找可以将一个以上的声明与一个名称相关联.声明被声明为一组重载函数(13.1). 名称解析成功后,将执行重载解析(13.3).仅在名称查找和函数重载解析(如果适用)成功之后,才考虑访问规则(条款11).只有在名称查找,函数重载解析(如果适用)和访问检查成功之后,名称声明所引入的属性才会在表达式处理中进一步使用(第5章).

3.4 Name lookup [basic.lookup]

1 The name lookup rules apply uniformly to all names (including typedef-names (7.1.3), namespace-names (7.3), and class-names (9.1)) wherever the grammar allows such names in the context discussed by a particular rule. Name lookup associates the use of a name with a declaration (3.1) of that name. Name lookup shall find an unambiguous declaration for the name (see 10.2). Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set of overloaded functions (13.1). Overload resolution (13.3) takes place after name lookup has succeeded. The access rules (Clause 11) are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the name’s declaration used further in expression processing (Clause 5).

(强调我的)

因此,我不确定编译器是否正确接受代码,尽管我不确定是否需要这样做.

I'd therefore say that the compiler(s) are correct to accept the code, although I'm not sure that they are required to do so.

要查看代码被拒绝,您需要实例化badbar.

To see the code being rejected, you need instantiate badbar.

这篇关于编译器将如何检查未实例化的模板代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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