4

endlこれがマニピュレータであり、内部的'\n'にバッファに配置され、バッファがフラッシュされることがわかっています。どこでendl定義されていますか?は何ですかendl、それはマクロですか、関数ですか、それとも変数ですか、それともクラスですか、それともオブジェクトですか? endl独自のマニピュレータを定義するにはどうすればよいですか?

cout << "hello" << endl ; /*what is endl and  where it is defined */
4

2 に答える 2

18

std::endl署名の関数テンプレートです:

template<class CharT, class Traits>
std::basic_ostream<CharT,Traits>& endl(std::basic_ostream<CharT,Traits>&);

オーバーstd::basic_ostream::operator<<ロードstd::basic_ostream<CharT,Traits>>::operator<<(std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&))は、特定のシグネチャの関数を受け入れます。

を実行するとstd::cout << std::endl、 でオーバーロードの解決が行われstd::endl、適切なテンプレート タイプが決定されstd::endl、関数がインスタンス化されます。これはその後、ポインターに崩壊し、 に渡されoperator<<ます。

std::basic_ostream::operator<<次に、問題の ostream で関数を呼び出し、戻り値を返します。何かのようなもの:

template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
std::basic_ostream<CharT, Traits>::operator<<(
  std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&)
) {
  return func(*this);
}

ただし、正確な実装はコンパイラ ライブラリ ライター1次第です。

std::endl改行を出力し、ostream に自分自身をフラッシュするように指示します。std::cout << std::endl;次の 2 行のコードでエミュレートできます。

std::cout.put(std::cout.widen('\n'));
std::cout.flush();

どのように正確std::endlに実装されるかはコンパイラ次第ですが、上記は (当然のことながら一般的なストリームで) どのように記述できるかの適​​切な概算です。

にアクセスできることが保証されていstd::endlます#include <ostream>stdライブラリから他のヘッダー ファイルをインクルードすると、アクセスできる可能性があります。それを正確に定義するファイルは、やはり実装次第です。

std::endl「ioマニピュレータ」として知られています。<<この手法は、io ストリームの状態を操作する関数を、呼び出しを連鎖させることにより、出力コマンドで「インライン」に設定できるようにすることを目的としています。

独自の ostream を作成するには、単一のタイプの ostream で動作させたい場合は、その種類をostream参照によって受け取り、それを参照によって返す関数を作成するだけです。現在は io マニピュレーターです。

一連のストリームを処理する場合は、次のようなテンプレートを作成します。

template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>& bob(std::basic_ostream<CharT, Traits>& os)
{
  return os << os.widen('b') << os.widen('o') << os.widen('b');
}

これは、 を出力する io マニピュレータになりました"bob"。それはあなたが問題にやりたいことを何でもすることができますbasic_ostream

代替プランは次のとおりです。

struct bob_t {
  template<class OS>
  OS& operator()(OS& os)const {
    return os << os.widen('b') << os.widen('o') << os.widen('b');
  }
  template<class OS>
  operator OS&(*)(OS&)() const {
    return [](OS& os)->OS&{ return bob_t{}(os); };
  }
};
static const bob_t bob;

wherebobは、io マニピュレーターとして使用できるオブジェクトになりました。


1この<<オーバーロードは型の関数ですA->(A->A)->A。基本的に、X を f に渡す代わりに、X と f を に渡し<<ますf(X)。純粋なシンタックス シュガー。

これstd::endlがテンプレートであるということは、この手法が原因で完全に転送するのが少し面倒であることを意味します。オーバーロードを使用してステートレス関数endl_t型を定義するoperator basic_ostream<CharT,Traits>&(*)(basic_ostream<CharT,Traits>&)()constことになるため、完全な転送プロキシを介してオーバーロード セットを渡すことができる場合があります。

次に、 のオーバーロード セット全体を に渡し、f:(A->A)<<下の次のレイヤー」にオーバーロードを解決させることができます。

于 2015-11-05T19:33:14.880 に答える
4

http://en.cppreference.com/w/cpp/io/manip/endl言います:

ヘッダーで定義<ostream>

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );

自分の endl マニピュレータをコーディングしたい場合、どのコードを書かなければなりませんか?

作成するだけの場合std::ostreamは、参照を受け入れてstd::ostream返す関数を作成します。汎用にしたい場合は、 のようにテンプレート化できますstd::endl

于 2015-11-05T19:29:28.200 に答える