微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 在依赖基类中找到的名称是否在实例化时隐藏命名空间名称?

使用以下代码,clang 3.0给出错误:成员访问表达式中“N”的查找是不明确的,而clang 3.4和 gcc 4.8都接受代码而没有错误.
struct B
{
    struct M
    {
        void f()
        {
        }
    };
};

namespace N
{
    struct M
    {
        void f()
        {
        }
    };
}

template<typename>
struct A : N::M,B::M
{
    typedef B N;
};

struct D : A<int>
{
    A<int> m;
    void f()
    {
        m.N::M::f(); // found class-name 'A<int>::N' (unambiguous)
    }
};

template<typename T>
struct C : A<T>
{
    A<T> m;
    void f()
    {
        m.N::M::f(); // found namespace-name 'N' (ambiguous?)
    }
};

template struct C<int>;

在咨询标准之后,对于C< T> :: f()中的表达式,我不清楚哪种行为是正确的.

因为N在对象表达式n(它是依赖的)的类的范围内并且在整个后缀表达式的上下文中查找(即,函数C< T> :: f()的范围),所以它有必要延迟查找直到实例化点.

在实例化的时刻,如果找到命名空间N和typedef A< T> :: N,则查找将是不明确的.只有当A< T> :: N的声明不被隐藏时,N的声明才可见.

问题是,在整个后缀表达式的上下文中“N”和“在模板的定义点”时,命名空间N是否应被视为被查找N的typedef A< T> :: N隐藏”.

引用C工作草案标准N3242 = 11-0012(2011年2月):

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 looked up both in the context of the
entire postfix-expression
and in the scope of the class of the object expression. If the name is found only in
the scope of the class of the object expression,the name shall refer to a class-name. If the name is found
only in the context of the entire postfix-expression,the name shall refer to a class-name or namespace-name. If the name is found in both contexts,the class-name-or-namespace-name shall refer to the same
entity.

14.6.4 Dependent name resolution [temp.dep.res]

In resolving dependent names,names from the following sources are considered:

Declarations that are visible at the point of deFinition of the template.

— Declarations from namespaces associated with the types of the function arguments both from the
instantiation context (14.6.4.1) and from the deFinition context.

解决方法

这是在C 11中改变的东西.你引用的文字
来自C 03;在C 11之前,这是不明确的,因为两者
使用查找,如果发现不同,它是一个错误
名.在C11中,文字是:

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 ]

基本上,这样就可以在类范围内查找查询权限
如果找到该名称,则不做另一个.

至于为什么这只会影响旧版本的模板的标准:我认为(很难确定任何事情这里)是因为在非模板的情况下,在整个后缀表达式的上下文中查找也在基类中找到typedef,所以这两个查找都解决了到同一个实体.在模板的情况下,查找整个后缀表达式的上下文不会占用记录依赖基类,只找到命名空间然后在C实例化之后,查找该类的范围找到typedef.由于两次查找找到不同的实体,名称绑定是不明确的.

原文地址:https://www.jb51.cc/c/112383.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐