Скрытые друзья: декларации и определения - PullRequest
0 голосов
/ 27 июня 2019

В своем недавнем блоге Энтони Уильямс рассказывает о скрытых друзьях.Основная идея, если я правильно понял, заключается в том, что функции, объявленные друзьями, не могут быть найдены ADL в определенных ситуациях.Простой пример:

namespace N {
    struct A {
        friend void foo(A) { }
    };

    struct B {
        operator A();
    };

    // (*)
    void bar(A) { }
}

void func() {
    N::A a;
    bar(a);   // OK, bar is found via ADL
    foo(a);   // OK, foo is found via ADL

    N::B b;
    bar(b);   // OK, bar is found via ADL
    foo(b);   // NOT OK, foo cannot be found
}

Во всех примерах в посте блога функции друзей определены внутри классов.Можно ли объявить функцию друга и затем определить ее позже в точке (*), чтобы она оставалась скрытой?Похоже, что скрытые друзья могут быть определены только в области видимости класса (или в другом модуле компиляции).

1 Ответ

1 голос
/ 27 июня 2019

Скрытые друзья должны быть полностью определены встроенными, то есть внутри определения класса. Да, если вы определяете друзей в другом месте, где определение может вызвать видимость пространства имен, это нарушит ограничения, основанные на том, что скрытые друзья будут найдены как совпадающие только с помощью поиска ADL, и, таким образом, будут кандидатами на разрешение перегрузки.

Подробнее о рекомендациях WG21 для указания скрытых друзей, отмечается, что скрытые друзья полностью определены в строке, как в этом фрагменте:

#include <ostream>
#include <compare>
class C  {
    friend ostream& operator << ( ostream&, C const& )  {}
    friend auto   operator <=>( C const&, C const& )  = default;
};
...