5.2.6. 名称空间

在模板实例化中进行名称查找时,必须在模板定义的上下文中查找某些名称, 可以在模板实例化的上下文中查找其他名称。 编译器实现两种不同的实例化查找算法:

相关名称查找是在 strict 模式下进行的,除非其他命令行选项显式地将其禁用,或者由配置标记或命令行选项启用相关名称处理。

相关名称查找处理

在进行相关名称查找时,编译器将实现标准中规定的实例化名称查找规则。 该处理要求进行非类原型实例化。 而这又需要使用标准要求的类型名称和模板关键字编写代码。

使用引用上下文进行查找

在不使用相关名称查找时,编译器使用与标准的两阶段查找规则近似的名称查找算法,但在某种程度上,它与现有代码和现有编译器更兼容。

如果将某个名称作为模板实例化一部分进行查找,但在实例化的局部上下文中找不到该名称,则在综合实例化上下文中进行查找。 该综合实例化上下文包括模板定义上下文中的名称以及实例化上下文中的名称。 例如:


namespace N

{

    int g(int);

    int x = 0;

    template <class T> struct A

    {

        T f(T t) { return g(t); }

        T f() { return x; }

    };

}



namespace M {

    int x = 99;

    double g(double);

    N::A<int> ai;

    int i = ai.f(0);        // N::A<int>::f(int) calls N::g(int)

    int i2 = ai.f();        // N::A<int>::f() returns 0 (= N::x)

    N::A<double> ad;

    double d = ad.f(0);     // N::A<double>::f(double) calls M::g(double)

    double d2 = ad.f();     // N::A<double>::f() also returns 0 (= N::x)

}

模板实例化中的名称查找在以下几个方面并不符合标准中的规则:

  • 虽然只有模板定义上下文中的名称被视为不是函数的名称,但是查找并不限于在定义模板处可见的那些名称。

  • 对于模板中的所有函数调用,将考虑引用模板的上下文中的函数。 引用上下文中的函数只对相关函数调用可见。

与自变量相关的查找

启用与自变量相关的查找后,通过与自变量相关的查找显示的函数可能与通过正常查找显示的函数发生重载。 标准要求即使在正常查找发现的名称为块 extern 声明时,也要进行这种重载。 编译器可实现这种重载,但在缺省模式下,在正常查找发现块 extern 时禁止与自变量相关的查找。

这意味着,即使程序不使用名称空间,程序也可能具有不同的行为,具体取决于是否使用与自变量相关的查找对其进行编译。 例如:


struct A { };

A operator+(A, double);

void f()

{

    A a1;

    A operator+(A, int);

    a1 + 1.0;          // calls operator+(A, double) with arg-dependent lookup

}                      // enabled but otherwise calls operator+(A, int);

Copyright © 2007 ARM Limited. All rights reserved. ARM DUI 0348AC
Non-Confidential