Я сделал это таким образом , как и некоторые другие люди. Имейте функцию Error
/ Log
/ Warning
/ etc, которая может выглядеть следующим образом
DiagnosticBuilder Error( ErrType type, string msg, int line );
Это вернет временный объект компоновщика, класс которого в основном определен как
struct DiagnosticBuilder {
DiagnosticBuilder(std::string const& format)
:m_emit(true), m_format(format)
{ }
DiagnosticBuilder(DiagnosticBuilder const& other)
:m_emit(other.m_emit), m_format(other.m_format), m_args(other.m_args) {
other.m_emit = false;
}
~DiagnosticBuilder() {
if(m_emit) {
/* iterate over m_format, and print the next arg
everytime you hit '%' */
}
}
DiagnosticBuilder &operator<<(string const& s) {
m_args.push_back(s);
return *this;
}
DiagnosticBuilder &operator<<(int n) {
std::ostringstream oss; oss << n;
m_args.push_back(oss.str());
return *this;
}
// ...
private:
mutable bool m_emit;
std::string m_format;
std::vector<std::string> m_args;
};
Так что, если вы строите лог-сообщение в цикле, пусть будет так
DiagnosticBuilder b(Error("The data is: %"));
/* do some loop */
b << result;
Как только деструктор строителя вызывается автоматически, сообщение отправляется. В основном вы бы использовали его анонимно
Error("Hello %, my name is %") << "dear" << "litb";