[英]Hidden friends: declarations and definitions
在他最近的博客文章中,安東尼威廉姆斯談到了隱藏的朋友。 如果我理解正確的話,主要思想是在某些情況下 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
}
在博客文章中的所有示例中,友元函數都是在類中定義的。 是否可以聲明一個友元函數,然后稍后在(*)
點定義它,使其保持隱藏狀態? 看起來隱藏的朋友只能在類范圍內(或在另一個編譯單元中)定義。
隱藏的朋友需要完全內聯定義,即在類定義的內部。 是的,如果您在其他地方定義友元,其中定義會導致命名空間可見性,它會打破基於隱藏友元的限制,僅通過 ADL 搜索才能找到匹配項,因此成為重載解析的候選者。
在WG21指定隱藏好友的更多建議中,注意到隱藏好友是完全內聯定義的,就像在這個片段中一樣:
#include <ostream>
#include <compare>
class C {
friend ostream& operator << ( ostream&, C const& ) {}
friend auto operator <=>( C const&, C const& ) = default;
};
隱藏的朋友可以被定義為不合時宜,但他們不會隱藏在那個 TU 中。 例如,請考慮以下標頭:
class A {
// this is hidden friend defined inline
friend int operator+(A, int) { return 0; }
// this is hidden friend defined out of line
friend int operator+(int, A);
// not a hidden friend (see below)
friend int operator+(A, A);
};
int operator+(A, A); // this is no longer hidden friend in any TU
然后是一個單獨的 cpp 文件:
#include "a.hpp"
// This is not a hidden friend in this TU, but is in other TUs.
int A::operator+(int, A) {
return 2;
}
當您的操作符/ADL 自定義點依賴於其他大型頭文件的實現時,這樣做很有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.