Original Question
I am writting a logging class where the goal is to be able to do this:
// thread one
Logger() << "Some string" << std::ios::hex << 45;
// thread two
Logger() << L"Some wide string" << std::endl;
Currently my Logger header looks something like this:
#pragma once;
#include <ostream>
class Logger
{
public:
Logger();
~Logger();
std::ostream* out_stream;
};
template <typename T>
Logger& operator<< (Logger& logger, T thing) {
*logger.out_stream << thing;
return logger;
}
Some notes about this class:
- Cross platform compatibility is not an issue.
- Inside of Logger.cpp there is a singleton class that takes care of creating the "real" ostream.
- The Logger constructor and deconstructor perform the necessary locking of the singleton.
I have three problems:
- How do I make the operator<< function a friend or member so I can set out_stream as private?
- How do I make the operator<< function work for manipulators?
- How can I add a specialization so that if T is a WCHAR* or std::wstring that it will convert it to char* or std::string before passing it to out_stream? (I can do the conversion. Losing high unicode characters isn't a problem in my case.)
Summary of things learned in answers:
- Put template BEFORE friend instead of after.
- std::ios::hex is not a manipulator. std::hex is a manipulator.
End Result
#pragma once
#include <ostream>
#include <string>
std::string ConvertWstringToString(std::wstring wstr);
class Logger
{
public:
Logger();
~Logger();
template <typename T>
Logger& operator<< (T data) {
*out << data;
return *this;
}
Logger& operator<< (std::wstring data) {
return *this << ConvertWstringToString(data);
}
Logger& operator<< (const wchar_t* data) {
std::wstring str(data);
return *this << str;
}
private:
std::ostream* out;
};