yohhoyの日記

技術的メモをしていきたい日記

endl, ends, flushの正体

C++標準ライブラリのI/Oストリームで提供される、std::endl, std::ends, std::flushについてメモ。

endl/ends/flushの実体は、標準ヘッダ <ostream>*1にて定義される関数テンプレート。C++標準規格ではマニピュレータ(manipulator)と呼称している。ぞれぞれの概要と、出力ストリームbasic_ostream<charT,traits> osに対する効果は下表の通り。

識別子 概要 効果
endl 改行文字の出力後にフラッシュ処理 os.put(os.widen('\n'));
os.flush();*2
ends 終端文字を出力 os.put(charT());*3
flush フラッシュ処理 os.flush();

通常は(1a)のようにオーバーロードされた<<演算子を介して利用する。(1b)は(1a)を通常の関数呼び出しに変形したもので、さらに27.7.3.6.3/p2に従って(1b)を変換すると(2)となる。

#include <iostream>
// (1a)
std::cout << std::endl;
// (1b)
std::cout.operator<<(std::endl);
// (2)
std::endl(std::cout);

N3337 27.7.3.1, 27.7.3.8より宣言を引用。見やすさため下線を引く。

template <class charT, class traits = char_traits<charT> >
class basic_ostream : virtual public basic_ios<charT,traits> {
public:
 basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
};

template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);

template <class charT, class traits>
basic_ostream<charT,traits>& ends(basic_ostream<charT,traits>& os);

template <class charT, class traits>
basic_ostream<charT,traits>& flush(basic_ostream<charT,traits>& os);

関連URL

*1:標準ヘッダ <iostream> でもOK。標準規格内で #include <ostream> することが保障されている。

*2:os.widen('\n') は改行文字 '\n' を型 charT に変換した値となる。charT=char なら単に '\n'。

*3:charT() はnull character。charT=char なら'\0'。