c++ - toyota - transmision manual
¿Cómo usar mi clase de registro como una transmisión estándar de C++? (4)
En la clase Logger, anule el operador <<.
Haga clic aquí para saber cómo implementar el operador <<.
También puede evitar las instrucciones de registro dentro del código usando la programación orientada a aspectos.
Tengo una clase de registrador que funciona, que saca algo de texto en un richtextbox (Win32, C ++). El problema es que siempre termino usándolo así:
stringstream ss;
ss << someInt << someString;
debugLogger.log(ss.str());
en su lugar, sería mucho más conveniente usarlo como una secuencia como en:
debugLogger << someInt << someString;
¿Hay una mejor manera que reenviar todo a una instancia interna de secuencia de cadenas? Si hiciera esto, ¿cuándo necesitaría enjuagar?
Necesita implementar el operator <<
apropiadamente para su clase. El patrón general se ve así:
template <typename T>
logger& operator <<(logger& log, T const& value) {
log.your_stringstream << value;
return log;
}
Observe que esto trata con referencias (no const
) ya que la operación modifica su registrador. También tenga en cuenta que debe devolver el parámetro de log
para que el encadenamiento funcione:
log << 1 << 2 << endl;
// is the same as:
((log << 1) << 2) << endl;
Si la operación más interna no devolvió la instancia de log
actual, todas las demás operaciones fallarían en tiempo de compilación (firma de método incorrecta) o se tragarían en el tiempo de ejecución.
La sobrecarga del operador de inserción << no es el camino a seguir. Deberá agregar sobrecargas para todas las funciones endl o cualquier otra definida por el usuario.
El camino a seguir es definir tu propio streambuf y vincularlo a una secuencia. Entonces, solo tienes que usar la transmisión.
Aquí hay algunos ejemplos simples:
- Inicio de sesión en C ++ por Petru Marginean, DDJ 05 de septiembre de 2007
- Clase de flujo de trabajo de Rutger EW van Beusekom , también verifique el .hpp junto con este archivo
Como señaló Luc Hermitte, hay un artículo "Iniciando sesión en C ++" que describe un enfoque muy claro para resolver este problema. En pocas palabras, dado que tiene una función como la siguiente:
void LogFunction(const std::string& str) {
// write to socket, file, console, e.t.c
std::cout << str << std::endl;
}
es posible escribir un contenedor para usarlo en std :: cout de la misma manera:
#include <sstream>
#include <functional>
#define LOG(loggingFuntion) /
Log(loggingFuntion).GetStream()
class Log {
using LogFunctionType = std::function<void(const std::string&)>;
public:
explicit Log(LogFunctionType logFunction) : m_logFunction(std::move(logFunction)) { }
std::ostringstream& GetStream() { return m_stringStream; }
~Log() { m_logFunction(m_stringStream.str()); }
private:
std::ostringstream m_stringStream;
LogFunctionType m_logFunction;
};
int main() {
LOG(LogFunction) << "some string " << 5 << " smth";
}
Además, hay una solución muy buena proporcionada por Stewart.