Logger estilo C ++ que suporta macro __LINE__ e outros

Eu quero fazer um Logger que possa ser usado comostd::cout, mas quero registrar alguns dados extras, como data, hora,__LINE__, __func__e__FILE__ que deve ser salvo no arquivo automaticamente.

Exemplo
ToolLogger log;
log << "some data" << std::endl;
Saída esperada
[14.11.2015 21:10:12.344 (main.cpp) (main,14): some data
Solução inadequada

Para fazer isso eu tenho que colocar macros como__LINE__ direto na linha em que chamo meu logger, caso contrário, as macros não funcionarão corretamente. Descobri que posso substituirstd::endl com a minha macro que fará essa magia negra assim:

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

A macrologendl usa variáveis estáticas do meuToolLogger classe para salvar os valores de__LINE__, __func__ e__FILE__ necessário mais tarde. Então, na verdade, usar o criador de logs ficará assim:

ToolLogger log;
log << "some data" << logendl;

Na classe eu tenho que sobrecarregar ooperator<< para que isso funcione, e eu preciso de dois deles. Um para tomar os valores normais comostd::string ouinte o outro para tirar ostd::endl manipulador. Aqui estão as coisas mais importantes da minha turma:

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;
Problema

O problema nesta solução é que posso usar meu logger de duas maneiras:

log << "some data" << logendl;   // correct //
log << "some data" << std::endl; // compiles -> wrong /

Então, na verdade, preciso remover ooperator<< da minha classe que levastd::endl manipulador e resolvê-lo de outra maneira, mas como fazê-lo? Eu estava pensando em mudarstd::endl nologendl macro para outro manipulador personalizado e, em seguida, esse manipulador personalizado fará o trabalho que está realmente fazendo ooperator<<, mas não tenho ideia de como fazê-lo. Estou procurando outra solução, alguma sugestão?

questionAnswers(3)

yourAnswerToTheQuestion