在struct中定义的调用友元函数需要前向声明吗?

the*_*mis 5 c++ friend

在阅读Karlsson的超越C++标准时,作者在类reference_counted的主体中定义了朋友函数intrusive_ptr_add_ref(参见第36页).在适当的时间使用Argument Dependent Lookup自动调用该函数.

从来没有看过在类的主体中定义的友元函数,我玩过并发现如果不使用ADL查找,gcc 4.4.3需要前向声明.实际上,如果没有前向声明,似乎没有办法引用adl_no.这是C++标准的一部分还是gcc的神器?(我没有Windows框所以不能尝试VC).

#include <cstdlib>
#include <iostream>


namespace {
    void adl_no();        // Remove this and it won't compile with gcc

    struct Q {
        friend void adl_yes(const Q&) {
            std::cout << "adl_yes" << std::endl;
        }

        friend void adl_no() {
            std::cout << "adl_NO" << std::endl;
        }
    };
}


int main(int argc, char** argv)
{
    adl_yes(Q());
    adl_no();

    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

CB *_*ley 6

是的,这种行为是标准的.该标准的相关部分是7.3.1.2 [namespace.memdef]第3段:

如果friend非本地类中的声明首先声明一个类或函数,那么友元类或函数是最内层封闭命名空间的成员.在该命名空间范围[...]中提供匹配的声明之前,通过简单的名称查找找不到该朋友的名称.如果调用了友元函数,则可以通过名称查找找到其名称,该名称查找考虑来自名称空间的函数和与函数参数(3.4.2)[即ADL]的类型相关联的类.