c++ - 使用 using 声明时,非限定名称查找如何工作?

标签 c++ language-lawyer name-lookup using-declaration name-hiding

根据 c++ 标准,这是良构还是良构?

namespace M { struct i {}; }
namespace N { static int i = 1; }
using M::i;
using N::i;
int main() { sizeof (i); }

Clang 拒绝它而 GCC 接受它。

根据 [namespace.udir-6] ( http://eel.is/c++draft/basic.namespace#namespace.udir-6 ):

If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions, the use of the name is ill-formed.

我们应该如何解读?请记住,每个 using 声明都通过 [namespace.udecl]p1 ( http://eel.is/c++draft/namespace.udecl#1 ) 声明一个名称:

A using-declaration introduces a name into the declarative region in which the using-declaration appears.

using-declaration:
   using typenameopt nested-name-specifier unqualified-id ;

The member name specified in a using-declaration is declared in the declarative region in which the using-declaration appears. [ Note: Only the specified name is so declared; specifying an enumeration name in a using-declaration does not declare its enumerators in the using-declaration's declarative region. — end note ] If a using-declaration names a constructor ([class.qual]), it implicitly declares a set of constructors in the class in which the using-declaration appears ([class.inhctor]); otherwise the name specified in a using-declaration is a synonym for a set of declarations in another namespace or class.

所以我们有 4 个名称 i 的声明。

sizeof(i) 中的 i 的非限定名称查找找到了哪些?

它是否只找到 using M::i;using N::i; 它们都在同一个命名空间(全局命名空间)中,所以程序是格式正确吗?

还是它只找到 struct i {};static int i = 1; 它们在不同的命名空间中,所以程序格式错误?

或者我们还有其他选择吗?

最佳答案

bogdan已经有了答案,但为了说明为什么您的直觉不正确,您引用了:

If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions, the use of the name is ill-formed.

但在示例中,我们有:

namespace M { 
    struct i {};           // declares M::i, entity class type
}
namespace N { 
    static int i = 1;      // declares N::i, entity variable
}
using M::i;                // declares ::i, synonym of M::i
using N::i;                // declares ::i, synonym of N::i
                           // hides (*) the other ::i
int main() { 
    sizeof (i); 
}

为了详细说明(*),我们在全局命名空间:: 中有两个i 声明。来自 [basic.scope.hiding]:

A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.

因此,对于同一范围内的两个 i,该类是隐藏的(不考虑 using-declarations 的顺序! ), sizeof(i) 指的是 ::iN::i 的同义词。两个 i 都在 same 命名空间 (::) 中,这就是为什么您的引述不适用的原因。这与您的 earlier question 不同,您使用的是 using-directives:

using namespace M;
using namespace N;

i 可以在两个不同的命名空间中找到,指的是两个不同的非功能实体。因此,错误。在这里,Clang 是错误的,而 GCC 是正确的。

关于c++ - 使用 using 声明时,非限定名称查找如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31711183/

相关文章:

c++ - 在模板中执行参数相关名称查找时的奇怪行为

c++ - 来自 n3290 :Argument-dependent name lookup 的一个点

c++ - 模板类和运算符重载

c++ - C++ 中的 std::ws 与 std::skipws

c++ - Paint Job Estimator C++

c++ - 是否有一个 "built in way"可以用 glog 记录一切直到程序崩溃?

c++ - clang/gcc 类特化不一致

c++ - 常量表达式中的静态成员访问

c++ - 如何包含名称中包含 `>` 的头文件?

c++ - 在我看来,[basic.lookup.argdep]/3 中的示例中有两个候选函数用于调用 g(parm, 1)