Skip to content

Instantly share code, notes, and snippets.

@1995eaton
Last active August 29, 2015 14:10
Show Gist options
  • Save 1995eaton/868371393e50a3c53d1a to your computer and use it in GitHub Desktop.
Save 1995eaton/868371393e50a3c53d1a to your computer and use it in GitHub Desktop.
C++ logging functions
#ifndef LOG_H
#define LOG_H
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cctype>
template <typename T>
struct TYPE;
#define typeof(E) TYPE<decltype(E)>();
template <typename T>
struct is_iterable {
template <typename U>
static char test(typename U::iterator*);
template <typename U>
static int test(...);
static constexpr bool value = sizeof test<T>(0) == 1;
};
template <typename A, typename B>
std::string STR(const std::pair<A, B>& first);
template <typename T,
typename std::enable_if<!is_iterable<T>::value>::type* = nullptr>
std::string STR(const T& first) {
std::ostringstream result;
result << first;
return result.str();
}
std::string STR(const char& first) {
std::string result = "'";
if (isprint(first)) {
result += first;
} else {
result += "\\x";
std::ostringstream hex;
hex << std::setw(8) << std::setfill('0') <<
std::hex << static_cast<int>(first);
result += hex.str().substr(6, 2);
}
result += "'";
return result;
}
template <typename T>
std::string STR(const std::basic_string<T>& first) {
return first;
}
std::string STR(const bool& first) {
return first ? "true" : "false";
}
template <typename T,
typename std::enable_if<is_iterable<T>::value>::type* = nullptr>
std::string STR(const T& first) {
std::ostringstream result;
result << '{';
for (const auto& it: first) {
result << STR(it) << ", ";
}
std::string rstring = result.str();
if (rstring.length() > 2 &&
rstring.back() == ' ' &&
rstring[rstring.length() - 2] == ',') {
rstring.pop_back();
rstring.pop_back();
}
return rstring + '}';
}
template <typename T>
struct SIZE;
template <typename T, size_t N>
struct SIZE<T[N]> {
static constexpr size_t value = N;
};
template <typename T, size_t N>
std::string STR(const T (&first)[N]) {
std::ostringstream result;
result << '{';
for (size_t i = 0; i < N; i++) {
result << STR(first[i]) << ", ";
}
std::string rstring = result.str();
if (rstring.length() > 2 &&
rstring.back() == ' ' &&
rstring[rstring.length() - 2] == ',') {
rstring.pop_back();
rstring.pop_back();
}
return rstring + '}';
}
template <typename A, typename B>
std::string STR(const std::pair<A, B>& first) {
std::ostringstream result;
result << STR(first.first);
result << ": ";
result << STR(first.second);
return result.str();
}
void LOG() {
std::cout << std::endl;
}
template <typename T>
void LOG(const T& first) {
std::cout << STR(first) << std::endl;
}
template <typename T, typename ...U>
void LOG(const T& first, const U&... rest) {
std::cout << STR(first) << ' ';
LOG(rest...);
}
void LOGF(const std::string& fmt) {
LOG(fmt);
}
template <typename T>
void LOGF(std::string fmt, const T& first) {
size_t index = fmt.find("{}");
if (index != std::string::npos)
fmt.replace(index, 2, STR(first));
else
fmt += " " + STR(first);
LOG(fmt);
}
template <typename T, typename ...U>
void LOGF(std::string fmt, const T& first, const U&... rest) {
size_t index = fmt.find("{}");
if (index != std::string::npos)
fmt.replace(index, 2, STR(first));
else
fmt += " " + STR(first);
LOGF(fmt, rest...);
}
template <typename ...T>
void print(T&&... args) {
LOG(std::forward<T>(args)...);
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment