c++ - 好友声明 : Is this a bug in clang?

标签 c++ c++11 namespaces language-lawyer name-lookup

§3.4.1/3 有以下示例:

typedef int f;
namespace N
{
    struct A
    {
        friend void f(A &);
        operator int();
        void g(A a)
        {
            int i = f(a);
        }
    };
}

编译时不会出现错误(请参阅 live example ),因为编译器看不到友元声明 N::A::f(A&)在名称 f 的普通查找中在声明中int i = f(a);根据 §7.3.1.2/3,这是正确的。

§7.3.1.2/3(重点是我的):

Every name first declared in a namespace is a member of that namespace. If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship).

现在,如果我们包含声明

struct A;
void f(A&);

在上面的代码片段 namespace N 中,之前struct A ,代码将正确地发出错误(参见 live example ),就像现在的函数 ::f(A&) 一样。通过普通查找名称 f 即可找到在表达式 int i = f(a); 中这符合 §7.3.1.2/3。

但是,如果我们包含声明

void f(A&);

namespace Nstruct A之后,令人惊讶的是,代码没有发出任何错误,请参阅 live example .

最佳答案

不,clang 正在做正确的事情。这不是一个错误。

您误读了本规范摘录的上下文。本段唯一要传达的内容涉及友元函数声明及其目标函数如何相互关联。 它与调用特定函数的通常规则没有任何关系,并且在这方面没有任何改变。

因此,编译不会失败,因为函数 f() 的原型(prototype)在您尝试使用它时尚未声明(而是找到具有相同名称的 typedef)。

如果您更改代码以在类外部实现 A::g() 成员,您会注意到当 f() 原型(prototype)出现时编译失败在实现之前,当原型(prototype)出现在它之后时成功——这正是您在缺少友元声明时所期望发生的情况。

关于c++ - 好友声明 : Is this a bug in clang?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25672745/

相关文章:

php - Symfony2 存储库标准文件夹或命名空间

c# - 类型名称 XXXX 在类型 XXXX 中不存在

c++ - 在正确的时间点将调试器附加到 VC++ 进程的最佳方法是什么?

c++ - 显示链接列表

c++ - "cout"没有命名类型错误

c++ - 模板函数作为模板参数

.net - 扩展 FCL 的系统命名空间真的是一种不好的做法吗?

C++ 用一个不同的语句重构公共(public)代码

c++ - 多变量埃尔米特样条

c++ - 为 C++ 字符串中的特殊符号 (") 赋予字面意义的有效 C++ 方法