解释[basic.scope.hiding] p2当非限定名称查找涉及使用指令 [英] Interpretation of [basic.scope.hiding]p2 when unqualified name lookup involves using-directives

查看:143
本文介绍了解释[basic.scope.hiding] p2当非限定名称查找涉及使用指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

c ++中有两种类型的名称隐藏:



1)正常名称隐藏:[basic.scope.hiding] p1( http://eel.is/c++draft/basic.scope.hiding#1 ) :


一个名称可以通过在
嵌套的声明区域或派生类class.member.lookup])。


2)隐藏在[basic.scope.hiding] a href =http://eel.is/c++draft/basic.scope.hiding#2 =nofollow> http://eel.is/c++draft/basic.scope.hiding# 2 ):


类名称([class.name])或枚举名称([dcl.enum]) be
被在同一作用域中声明的变量,数据成员,函数或枚举器的名称隐藏
。如果一个类或枚举名和一个
变量,数据成员,函数或枚举器在
中以相同的名称,类或枚举的相同范围(任何顺序)声明
name


我有兴趣了解更多信息关于当执行未限定名称查找时如何名称隐藏与使用指令交互。



对于第一种类型的名称隐藏,行为是非常清楚的。这是因为[basic.scope.hiding] p1已经根据[basic.lookup.unqual]( http://eel.is/c++draft/basic.lookup.unqual



没有为第二类名称隐藏做过。所以现在出现以下问题:



*)这第二种类型的名称隐藏应如何与涉及使用指令的非限定名称查询进行交互?



在标准的其他地方我找到[namespace.udir] p2( http://eel.is/c++draft/namespace.udir#2 ),我认为这是回答这个问题的关键:


using-directive指定在指定命名空间
中的名称可以在使用指令出现在
之后的use-directive的范围中使用。在非限定名称查找
([basic.lookup.unqual])中,名称显示,如同他们在中声明
最近的包含命名空间,包含
使用指令和指定的命名空间。 [注:在本上下文中,
contains表示包含直接或间接。 - end note]


将此规则的 as 部分应用于[basic.scope.hiding] p1给出了与[basic.lookup.unqual]部分中的规则的一致性。此应用程序也与[basic.scope.hiding] p4( http:/ /eel.is/c++draft/basic.scope.hiding#4 )所以这看起来很有前途。



因为这个,我想我们可以回答通过类似地将[namespace.udir] p2的如同部分应用到[basic.scope.hiding] p2中的问题*)。此应用程序也与[basic.scope.hiding] p4一致。我认为这也是c ++标准的最自然和最不复杂的解释。



然而问题是,Clang和GCC不像我一样解释。例如:

 命名空间N {static int i = 1; } 
namespace M {struct i {}; }
使用命名空间M;
使用命名空间N;
int main(){sizeof(i); }

根据我的解释,这个程序应该格式良好, i 应该作为整数变量查找。



在Clang的情况下,这个更复杂的解释会导致以下错误:

 命名空间N {static int i = 1; } 
namespace M {struct i {}; }
namespace P {
using N :: i;
using M :: i;
}
命名空间Q {using M :: i; }
使用命名空间P;
使用命名空间Q;
int main(){sizeof(i); }

没有错误,但更改

 使用命名空间P; 
使用命名空间Q;

 使用命名空间Q; 
使用命名空间P;

,我们得到名称查找模糊错误。

解决方案



这里的关键短语是:


一个名称可以通过同名的显式声明隐藏在嵌套的声明区域或派生的
类(10.2)中。



类名(9.1)或枚举名隐藏的变量名称,数据成员,
函数或枚举器在同一范围内声明


在这个例子中:

  namespace N {static int i = 1; } 
namespace M {struct i {}; }
使用命名空间M;
使用命名空间N;
int main(){sizeof(i); }

两个 i ,非嵌套作用域,所以没有隐藏。名称查找会在 :: 中查找他们 ,但这不是隐藏规则。



否则,从[basic.lookup]开始:


查找
查找名称的明确声明(见10.2)。名称查找可以将多个声明
与一个名称相关联,如果它发现该名称是一个函数名称;


:: 中没有明确的声明,所以这段代码是错误的,错误是正确的。对于另一个例子也是如此,所以事实上,有一些使用声明排序,哪个clang编译它是一个错误。



虽然这是非规范性的,但在[namespace.udir]中有一个例子,使得这种解释清楚:


[注意:特别是
变量,函数或枚举器的名称不隐藏类或枚举在不同的命名空间中声明为
。例如,

 命名空间A {
class X {};
externCint g();
externC ++int h();
}

命名空间B {
void X(int);
externCint g();
externC ++int h(int);
}

使用命名空间A;
使用命名空间B;
void f(){
X(1); // error:name X found in two namespaces
g(); // OK:name g指的是同一个实体
h(); // OK:overload resolution choices A :: h
}

note]



There are two types of name hiding in c++:

1) Normal name hiding: [basic.scope.hiding]p1 (http://eel.is/c++draft/basic.scope.hiding#1):

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class ([class.member.lookup]).

2) The special type of name hiding in [basic.scope.hiding]p2 (http://eel.is/c++draft/basic.scope.hiding#2):

A class name ([class.name]) or enumeration name ([dcl.enum]) 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'm interested to know about how name hiding interacts with using-directives when unqualified name lookup is performed.

For the first type of name hiding the behaviour is quite clear. This is because [basic.scope.hiding]p1 has been reformulated in terms of the rules in the section [basic.lookup.unqual] (http://eel.is/c++draft/basic.lookup.unqual)

The same has not been done for the second type of name hiding. So the following question now arises:

*) How should this second type of name hiding interact with unqualified name lookup that involves using-directives?

Looking elsewhere in the standard I find [namespace.udir]p2 (http://eel.is/c++draft/namespace.udir#2) and I think this is key to answering this question:

A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup ([basic.lookup.unqual]), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. [ Note: In this context, "contains" means "contains directly or indirectly". — end note ]

Applying the as if part of this rule to [basic.scope.hiding]p1 gives consistency with the rules in the section [basic.lookup.unqual]. This application is also consistent with [basic.scope.hiding]p4 (http://eel.is/c++draft/basic.scope.hiding#4) So this looks promising.

Because of this I think we can answer the question *) by similarly applying the as if part of [namespace.udir]p2 to [basic.scope.hiding]p2. This application is also consistent with [basic.scope.hiding]p4. I think this is also the most natural and least complex interpretation of the c++ standard.

The problem however is that Clang and GCC does not make the same interpretation as me. For example:

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

According to my interpretation this program should be well-formed and i should be looked up as the integer variable. Both Clang and GCC disagree with this by giving a name lookup ambiguity.

In the case of Clang this more complex interpretation leads to the following bug:

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

Gives no errors, but change

using namespace P;
using namespace Q;

into

using namespace Q;
using namespace P;

and we get name-lookup ambiguity error. GCC is at least consistent here.

Did I interpret the c++ standard correctly?

解决方案

The key phrases here I believe are:

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).

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.

In this example:

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

Both is are declared in different, non-nested scopes, so there is no hiding. Name lookup finds them as if they were declared in ::, but that's not what the rule for hiding stipulates.

Otherwise, we have, from [basic.lookup]:

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;

There is no unambiguous declaration in ::, so this code is ill-formed and the error is correct. The same is true for the other example, so the fact that there is some using-declaration ordering for which clang compiles it is a bug.

While this is non-normative, there is an example in [namespace.udir] that makes this interpretation clear:

[ Note: In particular, the name of a variable, function or enumerator does not hide the name of a class or enumeration declared in a different namespace. For example,

namespace A {
    class X { };
    extern "C" int g();
    extern "C++" int h();
}

namespace B {
    void X(int);
    extern "C" int g();
    extern "C++" int h(int);
}

using namespace A;
using namespace B;
void f() {
   X(1); // error: name X found in two namespaces
   g();  // OK: name g refers to the same entity
   h();  // OK: overload resolution selects A::h
}

—end note ]

这篇关于解释[basic.scope.hiding] p2当非限定名称查找涉及使用指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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