c++ - Clang 与 MSVC : Treatment of template function prototypes

标签 c++ templates visual-c++ clang

下面是一段测试代码,我分别用MSVC和Clang来对比编译结果。每个编译器的输出如下所示。 MSVC 假装未使用的模板声明甚至不存在。 Clang 产生错误。问题是,哪个编译器在这里最符合标准?

我见过依赖 MSVC 行为的遗留生产代码,但我不确定它是否可以继续依赖。

class S
{
    struct P {};
};

template<typename T>
S::P Bat(T);

在 MSVC10 中干净地编译:

E:\clangbuild\bin\Release>cl /c /nologo test.cpp
test.cpp

在 Clang 中产生错误:

E:\clangbuild\bin\Release>clang++ test.cpp
test.cpp:9:4: error: 'P' is a private member of 'S'
S::P Bat(T);
   ^
test.cpp:5:9: note: implicitly declared private here
struct P {};
        ^
1 error generated.

最佳答案

由于 C++ 中的两阶段名称查找,此操作失败。

在第一阶段,当模板最初被解析时,在它被实例化之前很久,编译器解析模板并查找任何非依赖名称。 S::P 是一个非依赖名称,因此编译器试图查找它,但失败了,因为它是私有(private)的。

在第 2 阶段,当模板被实例化时,编译器将查找任何从属名称,这些名称可能因模板而异。

Clang 相当严格地遵循两阶段名称查找。但是,MSVC 有一个模板解析模型,它几乎将每次查找都延迟到实例化时间,这是阶段 2 的一部分。这种延迟是您的示例将使用 MSVC(不符合标准)而不是 clang 进行编译的原因。这是包含更多信息的链接:

The Dreaded Two-Phase Name Lookup

另外,这里是 C++ 标准中描述两阶段查找的部分。

14.6.8:

When looking for the declaration of a name used in a template definition, the usual lookup rules (3.4.1, 3.4.2) are used for non-dependent names. The lookup of names dependent on the template parameters is postponed until the actual template argument is known.

14.6.9:

If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.

那么3.4 Name lookup适用于你的部分:

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).

通过阅读这些部分可以清楚地看出您的程序格式错误。标准规定唯一应该推迟到实例化的事情是查找从属名称。非相关名称通过常规名称查找,其中包括访问规则。

关于c++ - Clang 与 MSVC : Treatment of template function prototypes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9303843/

相关文章:

c++ - 如何查找CStringArray中添加的数据个数

C++ 无法为高阶函数派生模板参数

visual-studio - Visual Studio 11 和处理 msvcr110.dll

visual-c++ - 如何为 Mappoint 中的图钉分配自定义图标?

c++ - 我想在 C++ 中为 map<> 的给定 KEY 返回一个 VALUE。如果 KEY 不在 map<> 中,返回什么?

c++ - 如何撤消opencv中单个点的透视变换

c++ - 字符串转换为数学表达式

c++ - 模板类的实例化错误

c++ - BOOST_PP_ITERATION 可变长度参数

qt - 使用 'cmd' 命令的 QProcess 不会导致命令行窗口