I am making a simple logging class with a pointer to std::ofstream or std::cerr .
Is there an easy way to use the smart pointer to automatically clean up no matter which stream is used?
The code should compile on clang ++, g ++ and VS2013.
the code
#include <iostream> #include <fstream> #include <string> class Logger { private: std::ostream * output_stream{ nullptr }; bool using_file{ false }; public: Logger() { output_stream = &std::cerr; using_file = false; } Logger(std::string file) { output_stream = new std::ofstream(file); using_file = true; } ~Logger() { if (using_file) { delete output_stream; } } template<typename T> void log(T info) { *output_stream << info << std::endl; } }; class tmp { int i{ 4 }; friend std::ostream & operator<<(std::ostream &os, const tmp& p); }; std::ostream &operator<<(std::ostream &os, const tmp& p) { return os << pi; } int main() { tmp t; Logger logger; logger.log(t); system("pause"); return 0; }
Attempts
std::unique_ptr
I can use std::unique_ptr for the file as follows:
std::unique_ptr<std::ostream> p; p = std::make_unique<std::ofstream>("file.txt"); *p << "hi there" << std::endl;
Trying this with std::cout warns me of a remote function (assuming a constructor.
std::unique_ptr<std::ostream> p2; p2 = std::make_unique<std::ostream>(std::cout); *p2 << "hey" << std::endl;
std::shared_ptr
Because std::unique_ptr is only for owning things, and std::cout should not belong, I thought I would try std::shared_ptr
std::shared_ptr<std::ostream> p; p = std::make_shared<std::ostream>(std::cout); *p << "hola" << std::endl;
It gives me the same error with remote constructor. p = &std::cout complains about type mismatch, so it doesn't work either.
source share