首页 文章

在类模板中可见的朋友函数名称

提问于
浏览
2

请考虑以下示例:

template <typename T>
class C
{
    public:
        friend void f() {}
        friend void f(C<T>) {}
};

C<int> c;

void g(C<int>* p)
{
     f(); 
     f(*p);
}

使用GCC 5.2进行编译会引发以下编译错误:

no matching function for call to 'f()'

但标准在14.6.5中说:

可以在类模板中声明好友类或函数 . 实例化模板时,会将其朋友的名称视为在实例化时明确声明了特化 .

为什么这不能编译?在GCC 3.4中,它通过了 .

2 回答

  • 3

    f 只能通过参数依赖名称查找(ADL)找到 . 第二个调用编译,因为作为参数传递的 p 的指针是 C<int> 类型 - 这会导致ADL跳入并检查其他不可见的函数 . 实际上,根本无法找到 f 的第一个重载,因为没有办法将关联传递给 C 的任何特化 .

    只需看看你的报价,[temp.inject]/2

    与非模板类一样,除非在命名空间作用域(11.3)中显式声明,否则在普通查找期间,类模板特化的名称空间作用域友元函数的名称是不可见的 . 这些名称可以在相关类别的规则下找到(3.4.2) . 141 141)在声明模板或实例化模板时,朋友声明不会将新名称引入任何范围 .

  • 1

    f() 的调用与类 C 无关,因此它的朋友不会在重载决策中使用 .

    在另一个调用 f(*p) 中,参数是类类型,因此检查类的类和命名空间以查找可能的候选项 . 这样编译器将找到 f 函数并使用重载决策来选择合适的函数 .

相关问题