ストリーム演算子を使用するロギング クラスを実装しています。基本的な考え方は、カスタム型が を実装しoperator<<
て、ロギングの読み取り可能な表現を提供できるというものです。ロギング クラスは、さまざまなメッセージを「収集」し、破棄時に単一のロギング エントリとして (syslog などに) 転送します。
class log_stream : public std::ostringstream
{
inline ~log_stream()
{
forward_to_log(str().c_str());
}
};
class custom_type
{
};
std::ostream &operator<<(std::ostream &stream, const custom_type &)
{
stream << "<custom_type data>";
return stream;
}
log_stream() << "error in custom type: " << custom_type_variable;
これは、ステートメントが std::ostream からのオーバーロードで開始されず、代わりに直接カスタム型で開始されない場合を除いて、実際には非常にうまく機能します。
log_stream() << custom_type_variable; // no known conversion from 'log_stream'
// to 'basic_ostream<char, ...>&
// for 1st argument
is log_stream
-a ostringstream
is-a basic_ostringstream
is-a basic_ostream
. 何か案は?
operator<<
さらに、オーバーロードをlog_stream&
直接提供する方法はありますstd::ostream
か?log_stream
fstream
編集#1
「r値対応」operator<<
が追加された場合、最初の問題は解決されます。
template <typename Type> inline log_stream &operator<<(log_stream &&stream, Type&& type)
{
return operator<<(stream, std::forward<Type>(type));
}
ただし、基本クラスへの型変換で現在/まだ壊れています(それostringstream
またはostream
)。
log_stream() << custom_type(); // OK
log_stream() << custom_type() << "text"; // OK
log_stream() << "next"; // non-const lvalue reference to type 'log_stream' cannot bind
// to a value of unrelated type 'basic_ostream<char, ...>'
basic_ostream<char, ...>
タイプが無関係なのはなぜですか?の基本クラスであり、log_stream
ここでこの基本クラスへの参照を取得できるはずですよね?
編集#2
もちろん、 memberoperator<<
を呼び出す必要があります。これにより、機能します。
template <typename Type> inline log_stream &operator<<(log_stream &&stream, Type&& type)
{
stream << std::forward<Type>(type);
return stream;
}
したがって、問題は C++11 で解決されますが、C++03 ( argh )ではまだ機能しません。
頭に浮かぶ解決策の 1 つは、「r 値から l 値への変換演算子」を最短形式で提供することoperator()
です。
class log_stream
{
inline log_stream &()()
{
return *this;
}
}
log_stream()() << custom_type() << "text";
きれいではありませんが、何か。より良い(よりきれいな)アイデアはありますか?