加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 是否应该在类成员访问表达式中为依赖类/名称空间名称延迟名

发布时间:2020-12-16 07:05:33 所属栏目:百科 来源:网络整理
导读:clang和 gcc都拒绝以下代码 templatetypename Tvoid f(T t){ t.Dependent::f(); // clang accepts,gcc rejects t.operator Dependent*(); // both reject}struct Dependent{ void f();};struct A : Dependent{ operator Dependent*();};template void fA(A);
clang和 gcc都拒绝以下代码

template<typename T>
void f(T t)
{
    t.Dependent::f(); // clang accepts,gcc rejects
    t.operator Dependent*(); // both reject
}

struct Dependent
{
     void f();
};

struct A : Dependent
{
     operator Dependent*();
};

template void f<A>(A);

我对该标准的解读表明这两种表达都应该被接受.

在这两种情况下,Dependent只能是类型名称.

在这两种情况下,名称Dependent将“在对象表达式的类中查找”t.由于t是依赖于类型的表达式,因此应该延迟查找,直到模板被实例化为止.

有什么我想念的吗?

编辑:如果打算这样的名称不依赖,这个决定的理由是什么?我可以看到,如果实现者不必延迟对t.operator X :: Dependent *或tX :: Dependent :: f这样的构造的评估,它会使实现者的生活更轻松,其中X可以是命名空间或类型名称.我不清楚这是否是当前措辞的预期或非预期的副作用.

C工作草案N3337的相关引用:

3.4.5 Class member access [basic.lookup.classref]

If the id-expression in a class member access is a qualified-id of the form
class-name-or-namespace-name::…
the class-name-or-namespace-name following the . or -> operator is first looked up in the class of the
object expression
and the name,if found,is used. Otherwise it is looked up in the context of the entire
postfix-expression. [ Note: See 3.4.3,which describes the lookup of a name before ::,which will only find a
type or namespace name
. —end note ]

If the id-expression is a conversion-function-id,its conversion-type-id is first looked up in the class of the
object expression
and the name,is used. Otherwise it is looked up in the context of the entire
postfix-expression. In each of these lookups,only names that denote types or templates whose specializations
are types are considered
.

14.6.2 Dependent names [temp.dep]

Inside a template,some constructs have semantics which may differ from one instantiation to another. Such a
construct depends on the template parameters. In particular,types and expressions may depend on the type
and/or value of template parameters (as determined by the template arguments) and this determines the
context for name lookup for certain names. Expressions may be type-dependent (on the type of a template
parameter) or value-dependent (on the value of a non-type template parameter).

[…]

Such names are unbound and are looked up at the point of the template instantiation (14.6.4.1) in both the
context of the template definition and the context of the point of instantiation.

14.6.2.1 Dependent types [temp.dep.type]

A name is a member of an unknown specialization if it is

[…]

An id-expression denoting the member in a class member access expression (5.2.5) in which either

— the type of the object expression is the current instantiation,the current instantiation has at least
one dependent base class,and name lookup of the id-expression does not find a member of the
current instantiation or a non-dependent base class thereof; or

the type of the object expression is dependent and is not the current instantiation.

[…]

A type is dependent if it is

a member of an unknown specialization,

解决方法

1

以下是我认为你的第一个案例,t.Dependent :: f的工作原理.首先,我相信(意思是,我不完全确定)14.6.2.1p5应该说“unqualified-id”而不是“id-expression”.但与此无关,你的名字Dependent :: f实际上是由两个名字组成的(在标准中,每个嵌套的嵌套名称说明符后跟一个成员名称称为“qualified-id”,即使是语法上的,这些也不是qual-id productions.所以名字foo :: bar :: baz是一个限定id,但也包含另外一个“qualified-id”.

依赖和依赖:: f.前者不是“表示成员访问表达式中成员的id-expression”,因此您不能简单地应用适用于Dependent :: f的规则也适用于Dependent.

因此,依赖性是非依赖性的,尽管需要在依赖类型中查找,但必须在定义时找到它.我个人认为我们应该有一个子句说“当查找限定符依赖于类型的限定符时,名称查找会产生一个空结果.”,要优雅地处理这些“强制名称查找立即执行” .所以无论如何,最后,我认为你的第一个案例是由于没有找到Dependent而形成不良(第3.4条不能仅仅在第14条的主管上决定该名称实际上是依赖的).

2

对于您的其他情况,操作符Dependent,事情变得更容易.您还有两个名称,Dependent和operator Dependent.再一次,我没有发现任何说Dependent在这里是一个依赖名称(我不确定这是否是错误的.这超出了我的范围).

运算符函数名称的名称查找比较(例如,名称查找哈希表的相等函数)是“它们是由相同类型形成的转换函数-id”(3.8).这意味着为了形成名称本身(尚未进行名称查找!),您不仅需要像标识符一样提供词法拼写,而且还必须提供类型标识,这需要由相关.

在t.operator Dependent *中查找依赖的id-expression只是意味着语义类型比较被延迟了.尝试这个,这应该工作正常

struct Dependent; // forward decl at global scope
t.operator Dependent*(); // in function template

你的后续行动

If it is intended that such a name is not dependent,what is the rationale for this decision? I can see that it makes life easier for the implementor if they do not have to defer evaluation of a construct like t.operator X::Dependent* or t.X::Dependent::f where X could be either a namespace or a type name.

我不知道理由,但我认为你已经给了一个好点.这看起来非常符合在查找非限定名称时跳过依赖基类的规则.而且我认为适用于该案例的理由适用于此案例.这使得更容易在程序员的函数模板上进行推理,尤其是.

struct Dependent;

template<typename T>
void f(T t)
{
    t.Dependent::f();
    t.operator Dependent*();
}

代码看起来很好,但是如果T恰好有一个Dependent成员,突然Dependent会有一个不同的绑定(因为首先我们被告知要查看t的类,然后进入周围的范围).根据我目前对模板规则的理解,上面总是指周围范围的依赖,因此上述代码对于该缺陷是“安全的”.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读