ISO C ++草案(n3290)中的一点:3.4.3.2/1命名空间成员

时间:2011-08-10 06:55:13

标签: c++ namespaces c++11

ISO C ++草案(n3290)中的一点:3.4.3.2/1命名空间成员

  

如果qualified-id的嵌套名称说明符指定了命名空间,   查找嵌套名称说明符后指定的名称   命名空间的范围。 如果qualified-id以::开头,那么   在全局命名空间中查找::之后的名称。在任何一个   case,查找template-id的template-argument中的名称   在整个后缀表达式发生的上下文中。

这里可以解释一下BOLD部分......从早期的c ++ 03草案到c ++ 0x草案他添加了

  

如果qualified-id以::开头,则查找::之后的名称   在全局命名空间中。

任何人都可以用示例程序解释

4 个答案:

答案 0 :(得分:5)

::S是限定ID。

在qualified-id ::S::f中,S::是嵌套名称说明符。

在非正式术语中,嵌套名称说明符是id

的一部分
  • 从qual-id的最开始或在初始范围解析运算符(::)之后开始,如果在id的最开头出现
  • 以qualified-id。
  • 中的最后一个范围解析运算符结束

非常非正式地,id是qual-id或nonqualified-id。如果id是qualified-id,它实际上由两部分组成:嵌套名称说明符后跟一个unqualified-id。

假设:

struct  A {
    struct B {
        void F();
    };
};
  • A是一个不合格的身份。
  • ::A是一个限定ID,但没有嵌套名称说明符。
  • A::B是限定ID,A::是嵌套名称说明符。
  • ::A::B是限定ID,A::是嵌套名称说明符。
  • A::B::F是一个限定ID,B::A::B::都是嵌套名称说明符。
  • ::A::B::F是一个限定ID,B::A::B::都是嵌套名称说明符。

另一个例子:

#include <iostream>
using namespace std;

int count(0);                   // Used for iteration

class outer {
public:
    static int count;           // counts the number of outer classes
    class inner {
    public:
        static int count;       // counts the number of inner classes
    };
};

int outer::count(42);            // assume there are 42 outer classes
int outer::inner::count(32768);  // assume there are 2^15 inner classes
                                 // getting the hang of it?

int main() {
    // how do we access these numbers?
    //
    // using "count = ?" is quite ambiguous since we don't explicitly know which
    // count we are referring to.
    //
    // Nested name specifiers help us out here

    cout << ::count << endl;        // The iterator value
    cout << outer::count << endl;           // the number of outer classes instantiated
    cout << outer::inner::count << endl;    // the number of inner classes instantiated
    return 0;
}

编辑:

在回应你的评论时,我认为该陈述只是意味着模板的参数是在声明它们的上下文和行中处理的。例如,

f.~foo();中的

,foo在f.内查找,并且在foo<int>的范围内,使用foo引用它是有效的。

答案 1 :(得分:5)

它被称为合格名称查找 前导::引用全局命名空间。任何以::开头的限定标识符将始终通过本地名称空间中相同的命名标识符引用全局名称空间中的某个标识符。

namespace A
{ 
    namespace B
    {
        void doSomething();
    }
}

namespace Z 
{ 
    namespace A
    {  
        namespace B
        {
            void doSomething();
        } 
    }

    using namespace A::B // no leading :: refers to local namespace layer

    void doSomethingMore() 
    {
       doSomething(); // calls Z::A::B::doSomething();

    }
}

namespace Z
{
   namespace A
   { 
      namespace B
      {
          void doSomething();
      } 
   }

   using namespace ::A::B // leading :: refers to global namespace A
   void doSomethingMore() 
   {
        doSomething(); // calls ::A::B::doSomething();
   }
}

答案 2 :(得分:2)

粗体文字指的是两种不同的情况。第一部分是使用或不使用::作为前缀的区别。当限定名称以::开头时,将从空名称空间开始检查确切的名称空间,而如果不存在,则搜索将考虑嵌套名称空间:

namespace A {
    void f() { std::cout << "::A::f" << std::endl; }
}
namespace B {
    namespace A {
        void f() { std::cout << "::B::A::f" << std::endl; }
    }
    void g() {
        A::f();     // ::B::A::f
        ::A::f();   // ::A::f
    }
}

段落中的最后一句是指模板参数的具体内容,它告诉您查找不会在声明模板的命名空间中启动,而是在实例化它的命名空间中开始:

struct A {
    static void f() { std::cout << "::A::f()" << std::endl; }
};
template <typename T>
void f() {
    T::f();
}
namespace N {
    struct A {
        static void f() { std::cout << "::N::A::f()" << std::endl; }
    };
    void g() {
        f<A>();
    }
}

如果在模板名称空间中开始查找,则调用f<A>()将引用f<::A>,但标准中的该子句表明查找将在名称空间N内开始(其中整个后缀表达式发生),因此将调用::N::A::f()

答案 3 :(得分:0)

int a(1);

class someCls {
  private:
    int a;
  public:
    // Assigns this->a with the value of the global variable ::a.
    void assignFromGlobal() {
      a = ::a;
    }
};