2

のように使用できるロガーを作成したいのですが、日付、時刻、、、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::string1 つはまたはのような通常の値を取得するためのもので、もう 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<<方法がわかりません。他の解決策を探していますが、何か提案はありますか?

4

3 に答える 3

1

コンストラクターを持つLoggerAtクラスLoggerAt(const char*filename, int lineno)(おそらく のサブクラスstd::ostringstreamなど) がある場合は、次を定義します。

#define LOG(Out) do {LoggerAt(__FILE__,__LINE__) \
  << Out << std::endl; }while(0)

私の C++ プロジェクトのいくつかでは、次のようにコーディングしました。

void mom_inform_at(const char*fil, int lin, std::ostringstream& out)
{ out.flush(); 
  std::clog << fil << ":" << lin 
            << " INFORM: " << out.str() << std::endl ;
}

#define MOM_INFORM_AT(Fil,Lin,Output) do {      \
      std::ostringstream out_##Lin;               \
        out_##Lin << mom_outlog << Output ;       \
        mom_inform_at(Fil,Lin,out_##Lin);         \
    } while(0)

  #define MOM_INFORM_AT_BIS(Fil,Lin,Output) \
    MOM_INFORM_AT(Fil,Lin,Output)

  #define MOM_INFORM(Out)                         \
    MOM_INFORM_AT_BIS(__FILE__,__LINE__,Out)

そして、適切な機能を備えMOM_INFORM("x=" << " point:" << pt);た通常のPoint pt;例を想像できるようなものを使用しstd::ostream& operator << (std::ostream&out, const Point&point)ます。

便利 __FILE__に使用するに__LINE__は、マクロを使用する方がよいことに注意してください。

于 2015-11-14T20:28:10.207 に答える
0

私は自分の問題を解決しました。ここに投稿された他の回答はメインよりも優れている可能性がありますが、C ++で使用されているのと同じように簡単な方法でロガーを使用したかったstd::cout. また、私のソリューションは最適ではなく、他の問題につながる可能性がありますが、要件を満たしています。

カスタムを追加しましたstd::ostream

class CustomOstream : public std::ostream
{
  public:

    static CustomOstream& endl( CustomOstream& out )
    {
        return out;
    }
};

endlから関数を使用するようにマクロを変更しましたCustomOstream

#define __FILENAME__ (strrchr(__FILE__,'/') ? strrchr(__FILE__,'/') + 1 : __FILE__)
#define logendl \
    ((ToolLogger::fileName = __FILENAME__).empty() ? "" : "") \
    << ((ToolLogger::line = __LINE__) ? "" : "") \
    << ((ToolLogger::function = __func__).empty() ? "" : "") \
    << ToolLogger::CustomOstream::endl

また、operator<<メインクラスから変更されました

ToolLogger& operator<< (CustomOstream& (*f)(CustomOstream&))
{
    // do something //
    return *this;
}

ロガーは思い通りに使えるようになりました

log << "some data" << logendl;   // correct //
log << "some data" << std::endl; // won't compile -> correct //
于 2015-11-23T19:50:48.283 に答える