Одним из подходов является простой служебный класс, который использует стандартный поток в шаблонной функции-члене:
class LogStream {
public:
template <class T> LogStream& operator << (const T& rhs) {
stream << rhs;
return *this;
}
private:
std::stringstream stream;
};
Член потока, выполняющий всю работу, затем используется в деструкторе,
~LogStream() {
std::cout << stream.str() << std::endl;
}
и вы можете создавать временные объекты для передачи ваших аргументов для конкатенации:
LogStream() << "anything with std::ostream operator: " << 1.2345 << ' ' << std::hex << 12;
Дополнительное состояние (например, уровень журнала) можно передать конструктору, часто сопровождаемому вспомогательными функциями, такими как LogStream debug() { return LogStream(...); }
,Однако, когда вы достигнете определенного уровня сложности, вы, возможно, захотите переключиться на библиотеку журналов.