[C++] Logger with color support (Windows terminal)

06/01/2015 17:51 hazejp#1
I think the title says it all, I've written a small C++ logger for Windows & for more readability I added support for colored text.
Hope somebody has a use for it ;)

Code:
namespace Console
{
	struct ConsoleColor
	{
		enum : unsigned {
			BLACK, BLUE, GREEN, AQUA, RED, PURPLE,
			YELLOW, WHITE, GRAY, LIGHT_BLUE, LIGHT_GREEN,
			LIGHT_AQUA, LIGHT_RED, LIGHT_PURPLE,
			LIGHT_YELLOW, BRIGHT_WHITE
		};

		unsigned backgroundColor, foregroundColor;

		ConsoleColor(unsigned bgColor, unsigned fgColor)
			: backgroundColor(bgColor), foregroundColor(fgColor) {}
	} const restore = ConsoleColor(ConsoleColor::BLACK, ConsoleColor::WHITE);

	struct Logger
	{
		enum : unsigned {
			INFO_LEVEL, DEBUG_LEVEL, WARNING_LEVEL, ERROR_LEVEL
		};

		template<bool appendNewline = false>
		void Log(unsigned level, const std::string &str);
	} logger;

	const HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);

	std::ostream &operator<<(std::ostream &out, const ConsoleColor &color)
	{
		SetConsoleTextAttribute(hConOut, (color.backgroundColor << 4) | color.foregroundColor);
		return out;
	}

	template<bool appendNewline>
	void Logger::Log(unsigned level, const std::string &str)
	{
		std::string strLevel = (level == INFO_LEVEL) ? "[INFO] "
			: (level == DEBUG_LEVEL) ? "[DEBUG] "
			: (level == WARNING_LEVEL) ? "[WARNING] "
			: (level == ERROR_LEVEL) ? "[ERROR] " : "[LOG] ";
		unsigned fg = (level == INFO_LEVEL) ? ConsoleColor::LIGHT_GREEN
			: (level == DEBUG_LEVEL) ? ConsoleColor::PURPLE
			: (level == WARNING_LEVEL) ? ConsoleColor::LIGHT_YELLOW
			: (level == ERROR_LEVEL) ? ConsoleColor::LIGHT_RED : ConsoleColor::LIGHT_AQUA;
		std::cout << ConsoleColor(ConsoleColor::BLACK, fg)
			<< strLevel << restore << str;
		if (appendNewline) std::cout << '\n';
	}
}
UPDATE:
The code now uses templates ( + C++11 Variadic Templates) more extensively

Code:
#include <iostream>
#include <string>
#include <Windows.h>

struct ConsoleColor
{
    enum : unsigned {
        BLACK, BLUE, GREEN, AQUA, RED, PURPLE,
        YELLOW, WHITE, GRAY, LIGHT_BLUE, LIGHT_GREEN,
        LIGHT_AQUA, LIGHT_RED, LIGHT_PURPLE,
        LIGHT_YELLOW, BRIGHT_WHITE
    };
    
    unsigned backgroundColor, foregroundColor;
    
    ConsoleColor(unsigned bgColor, unsigned fgColor)
        : backgroundColor(bgColor), foregroundColor(fgColor) {}
} const restore = ConsoleColor(ConsoleColor::BLACK, ConsoleColor::WHITE);

struct Logger
{
    enum : unsigned {
        INFO_LEVEL, DEBUG_LEVEL, WARNING_LEVEL, ERROR_LEVEL
    };
    
    template<unsigned level, bool appendNewline = false>
    void Log(const std::string &str);
    template<unsigned level, bool appendNewLine, typename T, typename... Args>
    void Log(const std::string &str, T value, Args... args);
    template<typename T, typename... Args>
    void Log(T value, Args... args);
    template<typename T>
    void Log(T value);
} logger;

const HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);

std::ostream &operator<<(std::ostream &out, const ConsoleColor &color)
{
    SetConsoleTextAttribute(hConOut, (color.backgroundColor << 4) | color.foregroundColor);
    return out;
}

template<unsigned level, bool appendNewline>
void Logger::Log(const std::string &str)
{
    std::string strLevel = (level == INFO_LEVEL) ? "[INFO] "
        : (level == DEBUG_LEVEL) ? "[DEBUG] "
        : (level == WARNING_LEVEL) ? "[WARNING] "
        : (level == ERROR_LEVEL) ? "[ERROR] " : "[LOG] ";
    unsigned fg = (level == INFO_LEVEL) ? ConsoleColor::LIGHT_GREEN
        : (level == DEBUG_LEVEL) ? ConsoleColor::PURPLE
        : (level == WARNING_LEVEL) ? ConsoleColor::LIGHT_YELLOW
        : (level == ERROR_LEVEL) ? ConsoleColor::LIGHT_RED : ConsoleColor::LIGHT_AQUA;
    std::cout << ConsoleColor(ConsoleColor::BLACK, fg)
        << strLevel << restore << str;
    if (appendNewline) std::cout << 'n';
}

template<unsigned level, bool appendNewline, typename T, typename... Args>
void Logger::Log(const std::string &str, T value, Args... args)
{
    Log<level, appendNewline>(str);
    std::cout << value;
    Log(args...);
}
template<typename T>
void Logger::Log(T value)
{
    std::cout << value;
}
template<typename T, typename... Args>
void Logger::Log(T value, Args... args)
{
    std::cout << value;
    Log(args...);
}