在模板类之外定义友元函数的正确方法是什么?
What is the right way to define a friend function outside a template class?
如果我有一个普通的类,我可以在类中"注入"一个非自由的友元函数。 (除此之外,只有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 abov,因为现在我有一个真正的免费函数,它恰好是朋友而不是注入的朋友。
是否可以将案例 3 修改为与案例 2 100% 等效,并且仍然具有类外f
的定义?换句话说,是否可以注入一个在类外定义的友元函数?
我也试过这个,这给出了一个编译器错误:
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 的问题。在模板类中编写友元函数声明的正确方法是什么?
友元函数具有特殊的可见性规则(ADL 的特殊情况(,因此在类外部定义函数与在类内部定义函数是不同的。
此外,在情况 2 中,函数不是模板。 即使您每个模板都有一个。所以要在类外实现它, 您必须为每个T
实现每个friend double f(A<T> const& a);
。
该建议是最接近的解决方法:
- 你的功能(只有专业化(是朋友。
-
但是你的函数是模板(所以推论应该发生:
friend double f(A<T> const& a, T);
(情况 2(,f(A<float>{}, 42);
会成功
,而friend double f<>(A<T> const& a, T);
不会
(T
对于A<float>
float
,对于42
int
(( -
您的函数是在外部声明的,因此其可见性是"不同的"。
现在假设我需要根据稍后需要定义的类来实现
f
。在这种情况下,我尝试这样做:
其他解决方法是声明一个私有方法来完成这项工作,它允许您在类中定义朋友。 然后可以稍后定义该私有方法:
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);}
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- 在 c++ 中拥有一组结构的正确方法是什么?
- 通过JNI传递数据数组的最快方法是什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 在另一个类视图中添加最多2个图表的正确方法是什么
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 在C++中包含原型文件的正确方法是什么?
- 在 OpenCV C++ 中估计基本矩阵之前对相应点进行归一化的正确方法是什么?
- 在PostgreSQL中根据它们的ID选择大量行的最快方法是什么?
- 在OSX上使用CMake将Adobe的XMP工具包构建为共享库的最简单方法是什么?
- 将一系列整数放入类的最佳方法是什么?
- 从长整整转换为uint64_t的推荐方法是什么?
- 将此布尔值传递给此函数的最有效方法是什么?
- 通过比较C++中的行在 txt 文件中搜索的最简单方法是什么?