我尝试将模板化类的模板化成员函数的声明和定义分开,但最终出现以下错误和警告。
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu);
};
std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
../ hw06 / bigunsigned.h:13:77:警告:朋友声明 “的std :: ostream的和放;运算符&lt;&lt;(std :: ostream&amp;,const BigUnsigned&amp;)' 声明一个非模板函数[-Wnon-template-friend] 朋友std :: ostream&amp; operator&lt;&lt;(std :: ostream&amp; out,const BigUnsigned&amp; bu); ^ ../hw06/bigunsigned.h:13:77:注意:(如果这不是你的话 预期,确保已声明功能模板 并添加&lt;&gt;在这里的函数名称之后)../hw06/bigunsigned.h:16:51: 错误:无法使用模板名称'BigUnsigned'而没有参数 list std :: ostream&amp;运算符&lt;&lt;(std :: ostream&amp; out,const BigUnsigned&amp; BU){ ^ ../hw06/bigunsigned.h:在函数'std :: ostream&amp; operator&lt;&lt;(std :: ostream&amp;,const int&amp;)':../ hw06 / bigunsigned.h:17:28: 错误:请求'bu'中的成员'_integers',这是非类的 输入'const int' for(auto integer:bu._integers){ ^
当我加入这样的声明和定义时,一切都很好。
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
};
目的是将成员变量_integers打印到cout。可能是什么问题?
P.S。:使用this question我使这个函数免费,但没有帮助。
答案 0 :(得分:7)
BigUnsigned
是模板类型,所以
std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu)
无效,因为没有BigUnsigned
。您需要将朋友功能设为模板,以便您可以使用不同类型的BigUnsigned<some_type>
。
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
template<typename T>
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned<T>& bu);
};
template<typename T>
std::ostream& operator<<(std::ostream& out, const BigUnsigned<T>& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
第二个例子的作用是因为它在类中声明它使用类使用的模板类型。
答案 1 :(得分:4)
对the answer by NathanOliver的改进。
使用另一个答案,函数模板的所有实例化都是类模板的所有实例的friend
。
operator<< <int>
是friend
BigUnsigned<int>
以及BigUnsigned<double>
。
operator<< <double>
是friend
BigUnsigned<double>
以及BigUnsigned<FooBar>
。
您可以稍微更改声明,以便
operator<< <int>
是friend
BigUnsigned<int>
但不是BigUnsigned<double>
。
operator<< <double>
是friend
BigUnsigned<double>
但不是BigUnsigned<FooBar>
。
// Forward declaration of the class template.
template <typename I> class BigUnsigned;
// Forward declaration of the function template
template <typename I>
std::ostream& operator<<(std::ostream& out, const BigUnsigned<I>& bu);
// Change the friend-ship declaration in the class template.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
// Grant friend-ship only to a specific instantiation of the
// function template.
friend std::ostream& operator<< <I>(std::ostream& out, const BigUnsigned<I>& bu);
};
答案 2 :(得分:1)
添加第三个可提高可读性的变体是在类中定义友元函数:
#include <iostream>
template <typename T>
class Foo {
int test = 42;
// Note: 'Foo' inside the class body is basically a shortcut for 'Foo<T>'
// Below line is identical to: friend std::ostream& operator<< (std::ostream &os, Foo<T> const &foo)
friend std::ostream& operator<< (std::ostream &os, Foo const &foo) {
return os << foo.test;
}
};
int main () {
Foo<int> foo;
std::cout << foo << '\n';
}