优点和缺点 在类内为大型项目定义的内联朋友助手免费函数

Pros and Cons inline friend helper free function defined inside class for large project

本文关键字:朋友 函数 免费 定义 大型项目 缺点      更新时间:2023-10-16

我试图列出类外定义的辅助友元自由函数和类内定义的辅助友元自由函数之间的所有区别。

我正在考虑遵循规则:在类体内将所有帮助程序函数声明为朋友,但它并不广泛传播,所以我想知道我是否没有错过一些缺点。

让我们考虑我们有一个包含数十个类的命名空间,这些类是范围,在本例中,我们将begin放在类的主体内,end放在类的主体之外(显然目的不是评论这种不一致(

namespace nm
{
struct A
{
// ...
auto begin();
auto end();
friend auto
begin(const A& a)
{
return a.begin();
}
friend auto
end(const A&);
};

inline auto
end(const A& a)
{
return a.end();
}
// And tens of other class declaring `begin` and `end`.
}

优点:

  • 如果用户状态begin(x);并且 X 未实现begin则程序编译器不会列出所有重载的 BEGIN,因为只有在 X 实际实现 BEGIN 帮助程序函数时才可以访问 BEGIN。(begin 在命名空间范围内不可见:[classes.friends],N4659 中的第 7 项,类中定义的 friend 函数位于定义它的类的(词法(范围内(。如果用户声明end(x)并且在命名空间中声明了 x 的类型nm编译器将列出所有数十个end声明和潜在的重载。
  • begin(( 无法通过用户定义的转换函数访问,这可能是不需要的。

缺点:

  • 如果用户状态begin(x)并且 X 未实现begin则不会通知用户命名空间的其他类实际上存在begin
  • begin(( 无法通过用户定义的转换函数访问,这是需要的。

我是否错过了一些含义?如果帮助程序函数有两个参数怎么办?例如,如果它是operator==

"类中定义的友元函数在定义它的类的(词法(范围内">的意思是,在 A 的主体中声明的任何友元函数都属于 A 的命名空间(A 的词法作用域(。

换句话说:

namespace ns {
class A
{
static int bar()
{        
return 21;
}
public:
inline friend int foo(A& a)
{
return A::bar();
}
friend int foo2(A& a);
};
} // namespace ns

int foo2(ns::A& a)    // this will fail, since only ns::foo2() is friend of A
{
return foo(a);
}
namespace ns {
int foo2(ns::A& a)    // this works
{
return foo(a);
}
} // namespace ns

int main(int, const char**, const char**)
{
ns::A var;
return ns::foo(var) + ns::foo2(var);
}