4

如此处所述,模板实例化类成员函数上的 C++11 样式 SFINAE 和函数可见性使自由函数黯然失色。使用完全限定的名称通常有效,但是我很难使用其他类的内联声明的友元函数。考虑以下示例:

namespace N {

    struct C {
        friend int f(const C& c) {
            return 1;
        }
        friend int g(const C& c) {
            return 2;
        }
    };

    struct D {
        void f() {
            g(C{});            // ADL finds this
            ::N::f(C{});       // not found dispite full qualification
        }
    };
}

我想我明白问题是什么,如此处所述内联友元函数的范围是什么?内联友元函数通常使用 ADL 找到,并且在封闭的命名空间中并不真正可见。

所以我的问题是我应该如何更改我的代码以使其正常工作(除了重命名 f 之一)?

4

1 回答 1

5

这是因为friend线条:

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

解决方法是简单地提供该声明:

namespace N {

    struct C {
        friend int f(const C& c) {
            return 1;
        }
        friend int g(const C& c) {
            return 2;
        }
    };

    int f(const C& c);
    int g(const C& c);

    struct D {
        void f() {
            g(C{});
            ::N::f(C{});
        }
    };
}

现场演示

于 2014-06-11T17:14:02.117 回答