#include <iostream>
#include <sstream>
#include <stdexcept>
#include <iomanip>
class log_error
{
public:
log_error() = default;
log_error(log_error&& other) = default;
~log_error()
{
// Do whatever you want with the input
// Add a timestamp, process/thread id
// Write it to a file, send it to a server ...
std::cerr << "[ERROR] " << ss.str() << std::endl;
throw std::runtime_error(ss.str());
}
std::stringstream ss;
};
template<typename T>
log_error operator<<(log_error&& le, const T& t)
{
le.ss << t;
return std::move(le);
}
// For basic usage, you don't need a non-move operator<< / constructor.
// For more complex use you may want to provide it.
int main()
{
log_error() << "Ooops " << 23 << ", 0x" << std::setbase(16) << 23;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3N0cmVhbT4KI2luY2x1ZGUgPHN0ZGV4Y2VwdD4KI2luY2x1ZGUgPGlvbWFuaXA+CgpjbGFzcyBsb2dfZXJyb3IKewpwdWJsaWM6CiAgICBsb2dfZXJyb3IoKSA9IGRlZmF1bHQ7CiAgICBsb2dfZXJyb3IobG9nX2Vycm9yJiYgb3RoZXIpID0gZGVmYXVsdDsKICAgIH5sb2dfZXJyb3IoKQogICAgewogICAgICAgIC8vIERvIHdoYXRldmVyIHlvdSB3YW50IHdpdGggdGhlIGlucHV0CiAgICAgICAgLy8gQWRkIGEgdGltZXN0YW1wLCBwcm9jZXNzL3RocmVhZCBpZAogICAgICAgIC8vIFdyaXRlIGl0IHRvIGEgZmlsZSwgc2VuZCBpdCB0byBhIHNlcnZlciAuLi4KICAgICAgICBzdGQ6OmNlcnIgPDwgIltFUlJPUl0gIiA8PCBzcy5zdHIoKSA8PCBzdGQ6OmVuZGw7CiAgICAgICAgdGhyb3cgc3RkOjpydW50aW1lX2Vycm9yKHNzLnN0cigpKTsKICAgIH0KCiAgICBzdGQ6OnN0cmluZ3N0cmVhbSBzczsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lICBUPgpsb2dfZXJyb3Igb3BlcmF0b3I8PChsb2dfZXJyb3ImJiBsZSwgY29uc3QgVCYgdCkKewogICAgbGUuc3MgPDwgdDsKICAgIHJldHVybiBzdGQ6Om1vdmUobGUpOwp9CgovLyBGb3IgYmFzaWMgdXNhZ2UsIHlvdSBkb24ndCBuZWVkIGEgbm9uLW1vdmUgb3BlcmF0b3I8PCAvIGNvbnN0cnVjdG9yLgovLyBGb3IgbW9yZSBjb21wbGV4IHVzZSB5b3UgbWF5IHdhbnQgdG8gcHJvdmlkZSBpdC4KaW50IG1haW4oKQp7CiAgICBsb2dfZXJyb3IoKSA8PCAiT29vcHMgIiA8PCAyMyA8PCAiLCAweCIgPDwgc3RkOjpzZXRiYXNlKDE2KSA8PCAyMzsKICAgIHJldHVybiAwOwp9