gpt4 book ai didi

c++ - 在模板类之外定义友元函数的正确方法是什么?

转载 作者:行者123 更新时间:2023-11-27 23:43:10 39 4
gpt4 key购买 nike

如果我有一个普通类,我可以在类中“注入(inject)”一个非自由友元函数。 (除其他外,只能通过 ADL 找到)。

案例 1:

class A{
double p_;
friend double f(A const& a){return a.p_;}
};

如果这是一个模板类,我可以这样做:

案例 2:

template<class T>
class A{
double p_;
friend double f(A const& a){return a.p_;} // apparently A const& is a synomyn for A<T> const&
};

现在假设我需要根据稍后需要定义的类来实现f。我在这种情况下尝试这样做:

案例 3:

template<class T>
class A{
double p_;
friend double f(A const& a);
};
...

这已经给出了警告:“警告:友元声明‘double f(const A&)’声明了一个非模板函数 [-Wnon-template-friend]”。

根据编译器的建议,我可以这样做:

template<class T> class A;

template<class T> double f(A<T> const& a);

template<class T>
class A{
double p_;
friend double f<>(A const& a);
};

template<class T> double f(A<T> const& a){return a.p_;}

这需要更多的代码,我什至不确定它是否 100% 等同于上面的案例 2,这正是我想要的,因为现在我有一个真正自由的函数,它恰好是一个 friend 而不是注入(inject)的 friend 。

是否可以将案例 3 修改为 100% 等同于案例 2,并且仍然在类外定义 f?换句话说,是否可以注入(inject)类外定义的友元函数?


我也试过这个,它给出了一个编译器错误:

template<class T>
class A{
double p_;
friend double f(A<T> const& a);
};

template<class T> double A<T>::f(A<T> const& a){return a.p_;}

这个答案找到了相同的解决方案,但没有回答案例 3 等同于案例 2 的问题。What is the right way to write friend function declarations in template class?

最佳答案

友元函数具有特殊的可见性规则(ADL 的特殊情况),因此在类外部定义函数与在类内部定义函数无论如何是不同的。

此外,在情况 2 中,函数不是模板。即使每个模板都有一个。所以要在类之外实现它,你必须实现每个 friend double f(A<T> const& a);对于每个 T .

建议是最接近的解决方法:

  • 你的功能(仅特化)是 friend 。
  • 但是你的函数是模板(所以推导应该发生:
    friend double f(A<T> const& a, T); (案例 2),f(A<float>{}, 42);会成功
    friend double f<>(A<T> const& a, T);不会
    (T 将是 float 对于 A<float>int 对于 42 ))

  • 您的函数是在外部声明的,因此它的可见性“不同”

Now suppose that I need to implement f in terms of a class that needs to be defined later. I such case I tried doing this:

其他解决方法是声明一个私有(private)方法来完成这项工作,它允许您在类中定义友元。然后可以稍后定义该私有(private)方法:

template<class T>
class A{
double p_;

double do_f() const;
friend double f(A const& a){return a.do_f();}
};

// Thing needed by A<T>::do_f

template<class T>
double A<T>::do_f() const
{
// ...
}

如果返回类型是一个不完整的类型,你必须用 auto 做一个技巧返回(这适用于 g++11 和 clang++11)。

template<class T> class A;
class B;

template<class T>
class A{
B do_f() const;
friend auto f(A const& a){return a.do_f();} // not friend B f(...
};

class B{};

template<class T> B A<T>::do_f() const{return B{};}

int main(){A<double> a; f(a);}

关于c++ - 在模板类之外定义友元函数的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52749225/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com