在模板类之外定义朋友函数的正确方法是什么? [英] What is the right way to define a friend function outside a template class?

查看:112
本文介绍了在模板类之外定义朋友函数的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一个普通的课堂,我可以在课堂内注入一个非自由的朋友函数。 (这只能由ADL找到。)

If I have a normal class I can "inject" a non-free friend function inside the class. (That among other things can be only be found by ADL).

情况1:

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

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

If instead this is a template class I can do:

情况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 就需要稍后定义的类而言。我遇到这种情况,我尝试这样做:

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:

情况3:

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

这已经发出警告:警告:朋友声明'double f (const A&)'声明了非模板函数[-Wnon-template-friend]。

This already gives a warning: "warning: friend declaration ‘double f(const A&)’ declares a non-template function [-Wnon-template-friend]".

按照编译器的建议,我可以这样做:

Following the advice from the compiler I can do this:

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_;}

更多的代码,我什至不能确定它与我想要的情况2 abov是否100%等效,因为现在我有了一个真正的自由函数,恰好是朋友而不是注入的朋友。

Which requires so much more code and I am not even sure it is 100% equivalent to case 2 abov which is what I want, because now I have a truly free function that happens to be a friend instead of an injected friend.

案例3是否可以修改为100%等同于案例2,并且在类外仍然具有 f 的定义?换句话说,可以注入类之外定义的朋友功能吗?

Can case 3 be modified to be 100% equivalent to case 2 and still have a definition of f outside the class? In other words can one inject a friend function that is defined out of the class?

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的问题。

This answer finds the same solution but doesn't answer the question about case 3 being equivalent to case 2. What is the right way to write friend function declarations in template class?

推荐答案

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

Friend functions have special visibility rule (special case for ADL), so defining function outside the class is different than inside anyway.

此外,在第2种情况下,该功能为模板。即使每个模板都有一个。因此,要在类
之外实现它,您必须为每个<$ c实现每个 friend double f(A< C const& a); $ c> T 。

Moreover, in case 2, the function is not template. even if you have one for every template. So to implement it outside of the class, you would have to implement each friend double f(A<T> const& a); for every T.

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

The advice is the most close workaround:


  • 您的函数(仅专业化)是朋友。

  • ,但是您的函数是模板(因此应该进行推导:

    friend double f(A const& a,T); (情况2), f(A {},42) ; 将成功完成

    ,而 friend double f<(A T const& a,T); 不是

    T 将是 float 对于 A< float> int 表示 42 )))

  • Your function (only the specialization) is friend.
  • but your function is template (so deduction should occurs:
    with friend double f(A<T> const& a, T); (case 2), f(A<float>{}, 42); would succeed
    whereas friend double f<>(A<T> const& a, T); would not
    (T would be float for A<float> and int for 42))

您的函数在外部声明,因此其可见性为不同

your function is declared outside, so its visibility is "different".


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

其他解决方法是声明一个私有方法来完成这项工作,从而使您能够在类中有朋友定义。
然后可以在以后定义该私有方法:

Other work around is to declare a private method which will do the job, that allow you to have friend definition inside the class. That private method can then be defined later:

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 return(在g ++ 11和clang ++ 11中有效)。


If the return type is an incomplete type you have to do a trick with auto return (this works in g++11 and 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);}

这篇关于在模板类之外定义朋友函数的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆