posts - 18,  comments - 104,  trackbacks - 0
相信能看到这里的人,应该都用过std::endl吧,没见过?

1#include <iostream>
2
3using namespace std;
4
5int main()
6{
7    cout<<"Hello World!"<<endl;
8}

9

就是hello world后面那个。到底这个endl是个什么东西呢? 答案是:函数指针。
这是它的声明:

1template<class _Elem,
2    class _Traits> inline
3    basic_ostream<_Elem, _Traits>&
4    endl(basic_ostream<_Elem, _Traits>& _Ostr)

当然endl只输入输出流,输入流没有endl。所以输出流需要一个类似

basic_ostream& operator<<(basic_ostream&(*)(basic_ostream &))

函数来接受这个endl。

如果想写个类,比如一个log类,希望可以像标准流一样的输出,需要做什么呢?

1class Log
2{
3public:
4    teamplate <typename T>
5    Log& operator<<(const T& t)
6    {
7        // write t to log file.
8    }

9}
;

有了这个定义后,Log类就可以像标准输出流一样用了,比如:

1Log log;
2log<<123<<"ABC"<<132.32<<endl;

什么,编译出错,而且不止一个。上面说过,是endl引起的问题。
std::endl的定义本身就是个模板函数,用一个模板函数(编译时连参数都确定不下来)去推导模板参数,是极不现实的。
因为:endl有两个模板参数,_Elem 和 _Traits,其实_Traints 本身就是个以_Elem为参数的类模板,标准库里面有两个endl版本,
一个是 _Elem = char, 另一个是 _Elem = wchar.
所以编译器不能推导出Log类的operator<<的模板参数T,于是就错误了。

解决方案,之前也说过,需要一个接受函数指针的operator<<的重载版本。

1Log& operator<<(basic_ostream<char, char_traits<char>>& (*_Pfn)(basic_ostream<char, char_traits<char>>&))
2    {
3            // write endl to log using _Pfn
4    }

有这个定义,就可以顺利使用 <<std::endl 了。
当然可以为wchar定义一个operator<<来使用宽字符,这都是函数重载惹的祸呀。因为char和wchar算是endl函数两个重载版本。

问题解决了,说一下,同样的函数还有:

ends,输入一个字符串结束符。
flush,刷新流。
当然这俩个不常用。
posted on 2009-04-18 19:42 尹东斐 阅读(4292) 评论(4)  编辑 收藏 引用

FeedBack:
# re: std::endl 是什么?
2009-04-18 20:58 | OwnWaterloo
class slt_like_ostream {

slt_like_ostream&
operator<<(std::ios_base& (*pf)(std::ios_base& );

template< class C, class T >
slt_like_ostream&
operator<<(std::basic_ios< C,T>& (*pf)(std::basic_ios< C, T>&);

template< class C, class T >
operator<<
(std::basic_ostream< C,T>& (*pf)(std::basic_ostream< C,T>&);

};

这是stl对ostream的规范。
如果不实现这些规范, 不能与stl的其他组件(如std::endl)合作也是理所当然的。

  回复  更多评论
  
# re: std::endl 是什么?
2009-04-18 21:08 | 尹东斐
@OwnWaterloo

嗯,就是这样子的。
其实可以直接从basic_ostream继承,然后把stream_buf改成自己想要的输出方式就可以。  回复  更多评论
  
# re: std::endl 是什么?[未登录]
2009-04-22 17:20 | jans2002
以前遇到自己的Log不能用endl,就把endl都改为"\n"了。
感谢楼主讲解。  回复  更多评论
  
# re: std::endl 是什么?
2009-05-12 15:15 | zhaoyg
learn了  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用链接

留言簿(4)

随笔档案

文章分类

文章档案

相册

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜