のように使用できるロガーを作成したいのですが、日付、時刻、、、std::cout
などの追加データをログに記録して、ファイルに自動的に保存する必要があります。__LINE__
__func__
__FILE__
例
ToolLogger log;
log << "some data" << std::endl;
期待される出力
[14.11.2015 21:10:12.344 (main.cpp) (main,14): some data
不十分な解決策
これを行うには__LINE__
、ロガーを呼び出す行に direct などのマクロを配置する必要があります。そうしないと、マクロが正しく機能しません。std::endl
この黒魔術を次のように実行するマクロに置き換えることができることがわかりました。
#define __FILENAME__ (strrchr(__FILE__,'/') ? strrchr(__FILE__,'/') + 1 : __FILE__)
#define logendl \
((ToolLogger::fileName = __FILENAME__).empty() ? "" : "") \
<< ((ToolLogger::line = __LINE__) ? "" : "") \
<< ((ToolLogger::function = __func__).empty() ? "" : "") \
<< std::endl
このマクロlogendl
は、クラスの静的変数を使用してToolLogger
、 の値を保存し、__LINE__
後で必要に__func__
なり__FILE__
ます。したがって、実際にロガーを使用すると、次のようになります。
ToolLogger log;
log << "some data" << logendl;
クラスでは、これを機能させるために をオーバーロードするoperator<<
必要があり、そのうちの 2 つが必要です。std::string
1 つはまたはのような通常の値を取得するためのもので、もう 1 つはマニピュレータint
を取得するためのものです。std::endl
私のクラスで最も重要なことは次のとおりです。
class ToolLogger
{
public:
// standard operator<< //
template<typename T>
ToolLogger& operator<< (const T& str)
{
out << str;
return *this;
}
// operator<< for taking the std::endl manipulator //
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
typedef CoutType& (*StandardEndLine)(CoutType&);
ToolLogger& operator<<(StandardEndLine manip)
{
// save fileName, line and function to the file //
// and all what is already in stringstream //
// clear stringstream //
return *this;
}
static string fileName;
static int line;
static string function;
private:
ofstream file;
std::stringstream out;
};
string ToolLogger::fileName;
int ToolLogger::line;
string ToolLogger::function;
問題
このソリューションの問題は、ロガーを次の 2 つの方法で使用できることです。
log << "some data" << logendl; // correct //
log << "some data" << std::endl; // compiles -> wrong /
実際には、マニピュレータoperator<<
を取るクラスからを削除し、std::endl
別の方法で解決する必要がありますが、どうすればよいですか? マクロで他のカスタム マニピュレータに変更することを考えてstd::endl
いました。logendl
このカスタム マニピュレータは、実際に を行っている作業を行いますが、そのoperator<<
方法がわかりません。他の解決策を探していますが、何か提案はありますか?