2010-02-10 11 views
6

Quiero crear una clase registrador de tal manera que con una funcionalidad de esta manera:¿Cómo se escribe una clase de logger con cout interfaz de estilo (registrador << "Error:" << val << endl;)

Logger log; 
log << "Error: " << value << "seen" << endl; 

Esto debería imprimirme un mensaje formateado personalizado. P.ej. "12-09-2009 11:22:33 Error 5 visto"

Mi clase simple Actualmente tiene este aspecto:

class Logger { 
    private: 
     ostringstream oss; 
    public: 
     template <typename T> 
     Logger& operator<<(T a); 
} 

template <typename T> 
Logger& Logger::operator<<(T a) { 
    oss << a; 
    return *this; 
} 

void functionTest(void) { 
    Logger log; 
    log << "Error: " << 5 << " seen"; 
} 

Esto hará que oss para tener correctamente el búfer "Error: 5 visto". Pero no sé qué otra función necesito escribir/modificar para que algo se imprima en la pantalla. ¿Alguien sabe cómo hacer que esto funcione o hay otra forma de diseñar esta clase para que funcione mi funcionalidad?

+0

Pregunta:. La sello de tiempo. ¿Desea que se elimine el tiempo ?: ​​1) Cada expresión 2) Solo al comienzo de cada línea. ¿Desea que la línea termine automáticamente (según su prueba de función()). Básicamente debe ser un poco más específico sobre las condiciones bajo las cuales se agrega la marca de tiempo. Además, ¿está registrando en un archivo la consola? ¿Por qué necesita una clase especial y por qué no puede usar la secuencia estándar? –

+0

Martin, esta es solo una clase de muestra Desmonté la clase de registrador original solo con el problema relacionado con el uso del estilo de cout de registrador. –

Respuesta

1

Por lo que puedo ver, su registrador no es diferente de ostringstream. Simplemente toma lo que se le da y lo envía a la secuencia de cadenas. Si desea usarlo de esta manera, puede escribir un destructor para Logger que emite la cadena a cout.

Logger::~Logger() 
{ 
    std::cout<<getcurrentDateTimeAsString()<<" "<<oss.str()<<std::endl; 
} 

Pero por supuesto, esto no tendrá sentido si se crea y se utiliza en todo el programa de un registrador *.

0

Este (de this post) hace lo que quiere, pero le obliga a terminar cada línea con std :: endl:

class Logger { 
    private: 
     ostringstream oss; 
    public: 
     template <typename T> 
     Logger& operator<<(T a); 

    Logger& operator<<(std::ostream&(*f)(std::ostream&)) 
    { 
     if(f == std::endl) 
     { 
      std::cout << "12-09-2009 11:22:33" << oss.str() << std::endl; 
      oss.str(""); 
     } 
     return *this; 
    } 
}; 

template <typename T> 
Logger& Logger::operator<<(T a) { 
    oss << a; 
    return *this; 
} 

void functionTest(void) { 
    Logger log; 
    log << "Error: " << 5 << " seen" << std::endl; 
} 

int main() 
{ 
    functionTest(); 
} 

EDIT: Bueno acuerdo con su comentario que no parece se lo que quieras. Entonces te recomiendo que hagas como dicen los MSalters.

+0

Después de descargar el contenido cuando 'std :: endl' está superado, probablemente debas borrar el contenido de' oss' para que la salida no se repita en la línea siguiente. –

+0

No, esto también me vino a la mente. Pero no quiero forzar al usuario a usar siempre endl. ¿Cómo sabe cout cuando es el derecho de imprimir? No necesita un endl del usuario. –

+0

@David - gracias, corregido @Dheeraj - cout imprime las cosas a medida que llegan (problemas de almacenamiento a un lado). – Manuel

4

Detrás de cada std::ostream es un streambuf. Se puede recuperar y configurar a través de std::stream::rdbuf(). En particular, se puede envolver: puede proporcionar un objeto streambuf que posprocesará el texto transmitido. (postprocesado significa que no puede distinguir std::cout << 123; de std::cout << "123";)

En su caso particular, el post-procesamiento es bastante simple. Al comienzo de cada línea, quiere insertar algunos bytes. Esto simplemente significa que debe hacer un seguimiento de si ya ha emitido el prefijo para la línea actual. Si no, hágalo y configure la bandera. Y cuando veas una línea nueva, reiníciala. Su contenedor streambuf tiene solo un valor de bool.

1

La pregunta es cuándo y cómo se sincronizarán las informaciones, por línea. Por lo tanto, no importa si está almacenado en búfer o no, no hay más remedio que controlar la EOL y las informaciones en la línea, limpiándola o salidas directas.

Incluso si el destructor es para ser utilizado como EOL/ras,

{ log << [anything]; } como sintaxis soportes de pila en línea local para invocar destructor de registro de salida de los soportes, o como std :: endl, o bien debe ser utilizado.

A menos que la aplicación de meta-objeto con algún operador de agregación como '< <' o "+', usted está terminando todo el camino obligado a utilizar una forma explícita de poner fin a la línea y o color