operator<<(ostream&, const BigUnsigned<I>&) 必须只有一个参数
Posted
技术标签:
【中文标题】operator<<(ostream&, const BigUnsigned<I>&) 必须只有一个参数【英文标题】:operator<<(ostream&, const BigUnsigned<I>&) must take exactly one argument 【发布时间】:2016-04-27 22:53:15 【问题描述】:我试图将模板化类的模板化成员函数的声明和定义分开,但最终出现以下错误和警告。
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& 运算符)../hw06/bigunsigned.h:16:51: 错误:在没有参数的情况下无效使用模板名称“BigUnsigned” 列出 std::ostream& 运算符
当我像这样加入声明和定义时,一切都编译得很好。
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;
;
目的是将成员变量_整数打印到cout。可能是什么问题?
P.S.:使用 this question 我免费提供了该功能,但没有帮助。
【问题讨论】:
FWIW,对于 me 来说,BigUnsigned
成为一个容器似乎有点出人意料。不过,请注意这一点。
@erip,你为什么认为BigUnsigned
在这里是一个容器? operator<<
是一个格式化操作符。它与容器无关。
@JanHudec 不,但是将数据存储在std::vector
与容器有关。
@JanHudec BigUnsigned<std::string> bu"Hello, World"; /* oops, not really a big unsigned after all */
@erip,如果没有任意大小的东西并且某物是向量,您将无法获得任意精度。至于使用std::string
作为参数,想必没有显示的方法要求参数是数字类型。
【参考方案1】:
对the answer by NathanOliver的改进。
对于另一个答案,函数模板的所有实例化都是类模板的所有实例化的friend
s。
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);
;
【讨论】:
您介意添加内联定义朋友函数的可能性吗? @phresnel,你的意思是在BigUnsigned
的定义中定义它吗?
是的,当然,有时这会让事情更易于维护。
@phresnel,你不能按照我的建议在类模板定义中实现operator<<
函数。它必须在外部实施。
我刚刚意识到您也在定义一个免费的模板函数。你当然是对的;我将添加我的解决方案作为另一个答案。【参考方案2】:
添加第三个变体来稍微提高可读性,就是在类中定义友元函数:
#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';
【讨论】:
【参考方案3】:BigUnsigned
是一个模板类型所以
std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu)
由于没有BigUnsigned
,因此无法工作。您需要将朋友功能设为模板,以便您可以获取不同类型的BigUnsigned<some_type>
s。
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;
第二个示例有效的原因是,由于它是在类内部声明的,因此它使用该类使用的模板类型。
【讨论】:
@Slazer,实际上,你不想让template <typename T> std::ostream& operator<<(std::ostream&, const BigUnsigned<T>&)
成为BigUnsigned<I>
的朋友,因为I
和T
不相关,所以你不想在朋友声明前加上typename
。您只需要在类外定义前加上前缀;见 R Sahu 的回答。以上是关于operator<<(ostream&, const BigUnsigned<I>&) 必须只有一个参数的主要内容,如果未能解决你的问题,请参考以下文章
错误:'operator<<' 不匹配(操作数类型为'std::ostream' aka'std::basic_ostream<char>' 和'std::_List_iter
operator<<(ostream&, const BigUnsigned<I>&) 必须只有一个参数
spdlog 错误:“不知道如何格式化类型,包括 fmt/ostream.h 如果它提供了应该使用的 operator<<”