競技プログラミング用の C++ ライブラリ
#include "src/base/repr.hpp"値を、型名つきの C++ の初期化式のような文字列にします。デバッグ出力で、値の中身と型をまとめて確認できます。
repr(std::vector<int>{1, 2}); // "std::vector<int>{1, 2}"
repr(std::make_pair(1, 'x')); // "std::pair<int, char>{1, 'x'}"
repr(3LL); // "3ll"
int n = 3;
DEBUG(n); // 標準エラー出力に "n = 3"
| 名前 | 説明 |
|---|---|
repr(x) |
型名と初期化子を合わせた文字列 |
type_str(x) |
型名の文字列 ("std::vector<int>" など) |
initializer_str(x) |
初期化子の部分の文字列 ("{1, 2}" など) |
DEBUG(x) |
標準エラー出力に x = repr(x) を出す |
| 型 |
repr の例 |
|---|---|
int / long / long long
|
3 / 3l / 3ll
|
unsigned int / unsigned long / unsigned long long
|
3u / 3ul / 3ull
|
float / double / long double
|
1.500000f / 1.500000 / 1.500000l (std::to_string を使うので小数点以下 6 桁) |
char |
'a'、'\n' などのエスケープ、表示できない文字は 8 進数 |
const char* / std::string
|
"abc" / std::string{"abc"}
|
std::vector / std::set / std::array / std::map / std::pair
|
std::vector<int>{1, 2} など、要素も再帰的に文字列化 |
repr() などのメンバ関数を持つ型 |
そのメンバ関数の結果 (Range など) |
| それ以外 | T{} |
自作の型でも、メンバ関数 repr()、または type_str() と initializer_str() を定義すれば対応できます。
#pragma once
/**
* @file repr.hpp
* @brief 出力をそのままコンストラクタに使える文字列化 (repr)
*/
#include <array>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "traits.hpp"
namespace detail {
///////////////////////////////////////////////////////////////////
/////////////////////////// declaration ///////////////////////////
///////////////////////////////////////////////////////////////////
inline std::string type_str(const char*);
inline std::string initializer_str(const char*);
inline std::string repr(const char*);
inline std::string type_str(const char&);
inline std::string initializer_str(const char&);
inline std::string repr(const char&);
inline std::string type_str(const int&);
inline std::string initializer_str(const int&);
inline std::string repr(const int&);
inline std::string type_str(const long&);
inline std::string initializer_str(const long&);
inline std::string repr(const long&);
inline std::string type_str(const long long&);
inline std::string initializer_str(const long long&);
inline std::string repr(const long long&);
inline std::string type_str(const unsigned int&);
inline std::string initializer_str(const unsigned int&);
inline std::string repr(const unsigned int&);
inline std::string type_str(const unsigned long&);
inline std::string initializer_str(const unsigned long&);
inline std::string repr(const unsigned long&);
inline std::string type_str(const unsigned long long&);
inline std::string initializer_str(const unsigned long long&);
inline std::string repr(const unsigned long long&);
inline std::string type_str(const std::string&);
inline std::string initializer_str(const std::string&);
inline std::string repr(const std::string&);
inline std::string type_str(const float&);
inline std::string initializer_str(const float&);
inline std::string repr(const float&);
inline std::string type_str(const double&);
inline std::string initializer_str(const double&);
inline std::string repr(const double&);
inline std::string type_str(const long double&);
inline std::string initializer_str(const long double&);
inline std::string repr(const long double&);
template <typename T>
inline std::string type_str(const std::vector<T>&);
template <typename T>
inline std::string initializer_str(const std::vector<T>&);
template <typename T>
inline std::string repr(const std::vector<T>&);
template <typename T>
inline std::string type_str(const std::set<T>&);
template <typename T>
inline std::string initializer_str(const std::set<T>&);
template <typename T>
inline std::string repr(const std::set<T>&);
template <typename T1, typename T2>
inline std::string type_str(const std::pair<T1, T2>&);
template <typename T1, typename T2>
inline std::string initializer_str(const std::pair<T1, T2>&);
template <typename T1, typename T2>
inline std::string repr(const std::pair<T1, T2>&);
template <typename T1, typename T2>
inline std::string type_str(const std::map<T1, T2>&);
template <typename T1, typename T2>
inline std::string initializer_str(const std::map<T1, T2>&);
template <typename T1, typename T2>
inline std::string repr(const std::map<T1, T2>&);
template <typename T, size_t N>
inline std::string type_str(const std::array<T, N>&);
template <typename T, size_t N>
inline std::string initializer_str(const std::array<T, N>&);
template <typename T, size_t N>
inline std::string repr(const std::array<T, N>&);
///////////////////////////////////////////////////////////////////
/////////////////////////// definition ////////////////////////////
///////////////////////////////////////////////////////////////////
template <typename T, std::enable_if_t<not has_type_str_v<T>, std::nullptr_t> = nullptr>
inline std::string type_str(const T& t) {
return "T";
}
template <typename T, std::enable_if_t<has_type_str_v<T>, std::nullptr_t> = nullptr>
inline std::string type_str(const T& t) {
return t.type_str();
}
template <typename T, std::enable_if_t<not has_initializer_str_v<T>, std::nullptr_t> = nullptr>
inline std::string initializer_str(const T& t) {
return "{}";
}
template <typename T, std::enable_if_t<has_initializer_str_v<T>, std::nullptr_t> = nullptr>
inline std::string initializer_str(const T& t) {
return t.initializer_str();
}
template <typename T, std::enable_if_t<not has_repr_v<T>, std::nullptr_t> = nullptr>
inline std::string repr(const T& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T, std::enable_if_t<has_repr_v<T>, std::nullptr_t> = nullptr>
inline std::string repr(const T& t) {
return t.repr();
}
inline std::string type_str(const char*) {
return "char*";
}
inline std::string initializer_str(const char* t) {
return "\"" + std::string(t) + "\"";
}
inline std::string repr(const char* t) {
return detail::initializer_str(t);
}
inline std::string type_str(const char&) {
return "char";
}
inline std::string initializer_str(const char& t) {
// char が符号付きでも添字が負にならないように unsigned char で扱う (UTF-8 のバイトなど)
const unsigned char u = static_cast<unsigned char>(t);
std::vector<std::string> v(128, "");
v['\0'] = "\\0";
v['\a'] = "\\a";
v['\b'] = "\\b";
v['\f'] = "\\f";
v['\r'] = "\\r";
v['\n'] = "\\n";
v['\v'] = "\\v";
v['\''] = "\\'";
v['\\'] = "\\\\";
if (u < 128 and !v[u].empty())
return "'" + v[u] + "'";
if (32 <= u and u <= 126)
return "'" + std::string{t} + "'";
return "'\\" + std::to_string(u / 64) + std::to_string(u / 8 % 8) + std::to_string(u % 8) + "'";
}
inline std::string repr(const char& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const int&) {
return "int";
}
inline std::string initializer_str(const int& t) {
return std::to_string(t);
}
inline std::string repr(const int& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const long&) {
return "long";
}
inline std::string initializer_str(const long& t) {
return std::to_string(t) + "l";
}
inline std::string repr(const long& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const long long&) {
return "long long";
}
inline std::string initializer_str(const long long& t) {
return std::to_string(t) + "ll";
}
inline std::string repr(const long long& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const unsigned int&) {
return "unsigned int";
}
inline std::string initializer_str(const unsigned int& t) {
return std::to_string(t) + "u";
}
inline std::string repr(const unsigned int& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const unsigned long&) {
return "unsigned long";
}
inline std::string initializer_str(const unsigned long& t) {
return std::to_string(t) + "ul";
}
inline std::string repr(const unsigned long& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const unsigned long long&) {
return "unsigned long long";
}
inline std::string initializer_str(const unsigned long long& t) {
return std::to_string(t) + "ull";
}
inline std::string repr(const unsigned long long& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const std::string&) {
return "std::string";
}
inline std::string initializer_str(const std::string& t) {
return "\"" + t + "\"";
}
inline std::string repr(const std::string& t) {
return detail::type_str(t) + "{" + detail::initializer_str(t) + "}";
}
inline std::string type_str(const float&) {
return "float";
}
inline std::string initializer_str(const float& t) {
return std::to_string(t) + "f";
}
inline std::string repr(const float& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const double&) {
return "double";
}
inline std::string initializer_str(const double& t) {
return std::to_string(t);
}
inline std::string repr(const double& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const long double&) {
return "long double";
}
inline std::string initializer_str(const long double& t) {
return std::to_string(t) + "l";
}
inline std::string repr(const long double& t) {
return detail::initializer_str(t);
}
template <typename T>
inline std::string type_str(const std::vector<T>&) {
T t;
return "std::vector<" + detail::type_str(t) + ">";
}
template <typename T>
inline std::string initializer_str(const std::vector<T>& t) {
std::string ret;
ret += "{";
for (auto itr = t.begin(); itr != t.end(); itr++) {
if (itr != t.begin()) ret += ", ";
ret += detail::initializer_str(*itr);
}
ret += "}";
return ret;
}
template <typename T>
inline std::string repr(const std::vector<T>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T>
inline std::string type_str(const std::set<T>&) {
T t;
return "std::set<" + detail::type_str(t) + ">";
}
template <typename T>
inline std::string initializer_str(const std::set<T>& t) {
std::string ret;
ret += "{";
for (auto itr = t.begin(); itr != t.end(); itr++) {
if (itr != t.begin()) ret += ", ";
ret += detail::initializer_str(*itr);
}
ret += "}";
return ret;
}
template <typename T>
inline std::string repr(const std::set<T>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T1, typename T2>
inline std::string type_str(const std::pair<T1, T2>&) {
T1 t1;
T2 t2;
return "std::pair<" + detail::type_str(t1) + ", " + detail::type_str(t2) + ">";
}
template <typename T1, typename T2>
inline std::string initializer_str(const std::pair<T1, T2>& t) {
return "{" + detail::initializer_str(t.first) + ", " + detail::initializer_str(t.second) + "}";
}
template <typename T1, typename T2>
inline std::string repr(const std::pair<T1, T2>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T1, typename T2>
inline std::string type_str(const std::map<T1, T2>&) {
T1 t1;
T2 t2;
return "std::map<" + detail::type_str(t1) + ", " + detail::type_str(t2) + ">";
}
template <typename T1, typename T2>
inline std::string initializer_str(const std::map<T1, T2>& t) {
std::string ret;
ret += "{";
for (auto itr = t.begin(); itr != t.end(); itr++) {
if (itr != t.begin()) ret += ", ";
ret += "{";
ret += detail::initializer_str(itr->first);
ret += ", ";
ret += detail::initializer_str(itr->second);
ret += "}";
}
ret += "}";
return ret;
}
template <typename T1, typename T2>
inline std::string repr(const std::map<T1, T2>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T, size_t N>
inline std::string type_str(const std::array<T, N>&) {
T t;
return "std::array<" + detail::type_str(t) + ", " + std::to_string(N) + ">";
}
template <typename T, size_t N>
inline std::string initializer_str(const std::array<T, N>& t) {
std::string ret;
ret += "{";
for (auto itr = t.begin(); itr != t.end(); itr++) {
if (itr != t.begin()) ret += ", ";
ret += detail::initializer_str(*itr);
}
ret += "}";
return ret;
}
template <typename T, size_t N>
inline std::string repr(const std::array<T, N>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
} // namespace detail
template <typename T>
inline std::string type_str(const T& t) {
return detail::type_str(t);
}
template <typename T>
inline std::string initializer_str(const T& t) {
return detail::initializer_str(t);
}
template <typename T>
inline std::string repr(const T& t) {
return detail::repr(t);
}
#define DEBUG(x) { std::cerr << #x << " = " << repr(x) << std::endl; }#line 2 "src/base/repr.hpp"
/**
* @file repr.hpp
* @brief 出力をそのままコンストラクタに使える文字列化 (repr)
*/
#include <array>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#line 2 "src/base/traits.hpp"
/**
* @file traits.hpp
* @brief 型特性
*/
#include <cstddef>
#include <iterator>
#line 11 "src/base/traits.hpp"
#include <type_traits>
#line 13 "src/base/traits.hpp"
namespace detail {
using std::begin, std::end;
template <class T, class = void>
struct is_range_impl : std::false_type {};
template <class T>
struct is_range_impl<T, std::void_t<decltype(begin(std::declval<T&>()), end(std::declval<T&>()))>> : std::true_type {};
} // namespace detail
template <class T>
struct is_range : detail::is_range_impl<T>::type {};
template <class T>
inline constexpr bool is_range_v = is_range<T>::value;
#define HAS_METHOD(func_name) \
namespace detail { \
template <class T, class = void> \
struct has_##func_name##_impl : std::false_type {}; \
template <class T> \
struct has_##func_name##_impl<T, std::void_t<decltype(std::declval<T>().func_name())>> \
: std::true_type {}; \
} \
template <class T> \
struct has_##func_name : detail::has_##func_name##_impl<T>::type {}; \
template <class T> \
inline constexpr bool has_##func_name##_v = has_##func_name<T>::value;
#define HAS_METHOD_ARG(func_name) \
namespace detail { \
template <class T, typename U, class = void> \
struct has_##func_name##_impl : std::false_type {}; \
template <class T, typename U> \
struct has_##func_name##_impl<T, U, std::void_t<decltype(std::declval<T>().func_name(std::declval<U>()))>> \
: std::true_type {}; \
} \
template <class T, typename U> \
struct has_##func_name : detail::has_##func_name##_impl<T, U>::type {}; \
template <class T, typename U> \
inline constexpr bool has_##func_name##_v = has_##func_name<T, U>::value;
HAS_METHOD(repr)
HAS_METHOD(type_str)
HAS_METHOD(initializer_str)
HAS_METHOD(max)
HAS_METHOD(min)
HAS_METHOD(reversed)
HAS_METHOD(sorted)
HAS_METHOD(sum)
HAS_METHOD(product)
HAS_METHOD(product_xor)
HAS_METHOD_ARG(count)
HAS_METHOD_ARG(find)
HAS_METHOD_ARG(lower_bound)
HAS_METHOD_ARG(upper_bound)
#define ENABLE_IF_T_IMPL(expr) std::enable_if_t<expr, std::nullptr_t> = nullptr
#define ENABLE_IF_T(...) ENABLE_IF_T_IMPL((__VA_ARGS__))
template <class C>
using mem_value_type = typename C::value_type;
template <class C>
using mem_difference_type = typename C::difference_type;
namespace detail {
template <class T, class = void>
struct is_sorted_container_impl : std::false_type {};
template <class T>
struct is_sorted_container_impl<std::set<T>> : std::true_type {};
template <class T>
struct is_sorted_container_impl<std::multiset<T>> : std::true_type {};
} // namespace detail
template <class T>
struct is_sorted_container : detail::is_sorted_container_impl<T>::type {};
template <class T>
inline constexpr bool is_sorted_container_v = is_sorted_container<T>::value;
#line 17 "src/base/repr.hpp"
namespace detail {
///////////////////////////////////////////////////////////////////
/////////////////////////// declaration ///////////////////////////
///////////////////////////////////////////////////////////////////
inline std::string type_str(const char*);
inline std::string initializer_str(const char*);
inline std::string repr(const char*);
inline std::string type_str(const char&);
inline std::string initializer_str(const char&);
inline std::string repr(const char&);
inline std::string type_str(const int&);
inline std::string initializer_str(const int&);
inline std::string repr(const int&);
inline std::string type_str(const long&);
inline std::string initializer_str(const long&);
inline std::string repr(const long&);
inline std::string type_str(const long long&);
inline std::string initializer_str(const long long&);
inline std::string repr(const long long&);
inline std::string type_str(const unsigned int&);
inline std::string initializer_str(const unsigned int&);
inline std::string repr(const unsigned int&);
inline std::string type_str(const unsigned long&);
inline std::string initializer_str(const unsigned long&);
inline std::string repr(const unsigned long&);
inline std::string type_str(const unsigned long long&);
inline std::string initializer_str(const unsigned long long&);
inline std::string repr(const unsigned long long&);
inline std::string type_str(const std::string&);
inline std::string initializer_str(const std::string&);
inline std::string repr(const std::string&);
inline std::string type_str(const float&);
inline std::string initializer_str(const float&);
inline std::string repr(const float&);
inline std::string type_str(const double&);
inline std::string initializer_str(const double&);
inline std::string repr(const double&);
inline std::string type_str(const long double&);
inline std::string initializer_str(const long double&);
inline std::string repr(const long double&);
template <typename T>
inline std::string type_str(const std::vector<T>&);
template <typename T>
inline std::string initializer_str(const std::vector<T>&);
template <typename T>
inline std::string repr(const std::vector<T>&);
template <typename T>
inline std::string type_str(const std::set<T>&);
template <typename T>
inline std::string initializer_str(const std::set<T>&);
template <typename T>
inline std::string repr(const std::set<T>&);
template <typename T1, typename T2>
inline std::string type_str(const std::pair<T1, T2>&);
template <typename T1, typename T2>
inline std::string initializer_str(const std::pair<T1, T2>&);
template <typename T1, typename T2>
inline std::string repr(const std::pair<T1, T2>&);
template <typename T1, typename T2>
inline std::string type_str(const std::map<T1, T2>&);
template <typename T1, typename T2>
inline std::string initializer_str(const std::map<T1, T2>&);
template <typename T1, typename T2>
inline std::string repr(const std::map<T1, T2>&);
template <typename T, size_t N>
inline std::string type_str(const std::array<T, N>&);
template <typename T, size_t N>
inline std::string initializer_str(const std::array<T, N>&);
template <typename T, size_t N>
inline std::string repr(const std::array<T, N>&);
///////////////////////////////////////////////////////////////////
/////////////////////////// definition ////////////////////////////
///////////////////////////////////////////////////////////////////
template <typename T, std::enable_if_t<not has_type_str_v<T>, std::nullptr_t> = nullptr>
inline std::string type_str(const T& t) {
return "T";
}
template <typename T, std::enable_if_t<has_type_str_v<T>, std::nullptr_t> = nullptr>
inline std::string type_str(const T& t) {
return t.type_str();
}
template <typename T, std::enable_if_t<not has_initializer_str_v<T>, std::nullptr_t> = nullptr>
inline std::string initializer_str(const T& t) {
return "{}";
}
template <typename T, std::enable_if_t<has_initializer_str_v<T>, std::nullptr_t> = nullptr>
inline std::string initializer_str(const T& t) {
return t.initializer_str();
}
template <typename T, std::enable_if_t<not has_repr_v<T>, std::nullptr_t> = nullptr>
inline std::string repr(const T& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T, std::enable_if_t<has_repr_v<T>, std::nullptr_t> = nullptr>
inline std::string repr(const T& t) {
return t.repr();
}
inline std::string type_str(const char*) {
return "char*";
}
inline std::string initializer_str(const char* t) {
return "\"" + std::string(t) + "\"";
}
inline std::string repr(const char* t) {
return detail::initializer_str(t);
}
inline std::string type_str(const char&) {
return "char";
}
inline std::string initializer_str(const char& t) {
// char が符号付きでも添字が負にならないように unsigned char で扱う (UTF-8 のバイトなど)
const unsigned char u = static_cast<unsigned char>(t);
std::vector<std::string> v(128, "");
v['\0'] = "\\0";
v['\a'] = "\\a";
v['\b'] = "\\b";
v['\f'] = "\\f";
v['\r'] = "\\r";
v['\n'] = "\\n";
v['\v'] = "\\v";
v['\''] = "\\'";
v['\\'] = "\\\\";
if (u < 128 and !v[u].empty())
return "'" + v[u] + "'";
if (32 <= u and u <= 126)
return "'" + std::string{t} + "'";
return "'\\" + std::to_string(u / 64) + std::to_string(u / 8 % 8) + std::to_string(u % 8) + "'";
}
inline std::string repr(const char& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const int&) {
return "int";
}
inline std::string initializer_str(const int& t) {
return std::to_string(t);
}
inline std::string repr(const int& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const long&) {
return "long";
}
inline std::string initializer_str(const long& t) {
return std::to_string(t) + "l";
}
inline std::string repr(const long& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const long long&) {
return "long long";
}
inline std::string initializer_str(const long long& t) {
return std::to_string(t) + "ll";
}
inline std::string repr(const long long& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const unsigned int&) {
return "unsigned int";
}
inline std::string initializer_str(const unsigned int& t) {
return std::to_string(t) + "u";
}
inline std::string repr(const unsigned int& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const unsigned long&) {
return "unsigned long";
}
inline std::string initializer_str(const unsigned long& t) {
return std::to_string(t) + "ul";
}
inline std::string repr(const unsigned long& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const unsigned long long&) {
return "unsigned long long";
}
inline std::string initializer_str(const unsigned long long& t) {
return std::to_string(t) + "ull";
}
inline std::string repr(const unsigned long long& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const std::string&) {
return "std::string";
}
inline std::string initializer_str(const std::string& t) {
return "\"" + t + "\"";
}
inline std::string repr(const std::string& t) {
return detail::type_str(t) + "{" + detail::initializer_str(t) + "}";
}
inline std::string type_str(const float&) {
return "float";
}
inline std::string initializer_str(const float& t) {
return std::to_string(t) + "f";
}
inline std::string repr(const float& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const double&) {
return "double";
}
inline std::string initializer_str(const double& t) {
return std::to_string(t);
}
inline std::string repr(const double& t) {
return detail::initializer_str(t);
}
inline std::string type_str(const long double&) {
return "long double";
}
inline std::string initializer_str(const long double& t) {
return std::to_string(t) + "l";
}
inline std::string repr(const long double& t) {
return detail::initializer_str(t);
}
template <typename T>
inline std::string type_str(const std::vector<T>&) {
T t;
return "std::vector<" + detail::type_str(t) + ">";
}
template <typename T>
inline std::string initializer_str(const std::vector<T>& t) {
std::string ret;
ret += "{";
for (auto itr = t.begin(); itr != t.end(); itr++) {
if (itr != t.begin()) ret += ", ";
ret += detail::initializer_str(*itr);
}
ret += "}";
return ret;
}
template <typename T>
inline std::string repr(const std::vector<T>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T>
inline std::string type_str(const std::set<T>&) {
T t;
return "std::set<" + detail::type_str(t) + ">";
}
template <typename T>
inline std::string initializer_str(const std::set<T>& t) {
std::string ret;
ret += "{";
for (auto itr = t.begin(); itr != t.end(); itr++) {
if (itr != t.begin()) ret += ", ";
ret += detail::initializer_str(*itr);
}
ret += "}";
return ret;
}
template <typename T>
inline std::string repr(const std::set<T>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T1, typename T2>
inline std::string type_str(const std::pair<T1, T2>&) {
T1 t1;
T2 t2;
return "std::pair<" + detail::type_str(t1) + ", " + detail::type_str(t2) + ">";
}
template <typename T1, typename T2>
inline std::string initializer_str(const std::pair<T1, T2>& t) {
return "{" + detail::initializer_str(t.first) + ", " + detail::initializer_str(t.second) + "}";
}
template <typename T1, typename T2>
inline std::string repr(const std::pair<T1, T2>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T1, typename T2>
inline std::string type_str(const std::map<T1, T2>&) {
T1 t1;
T2 t2;
return "std::map<" + detail::type_str(t1) + ", " + detail::type_str(t2) + ">";
}
template <typename T1, typename T2>
inline std::string initializer_str(const std::map<T1, T2>& t) {
std::string ret;
ret += "{";
for (auto itr = t.begin(); itr != t.end(); itr++) {
if (itr != t.begin()) ret += ", ";
ret += "{";
ret += detail::initializer_str(itr->first);
ret += ", ";
ret += detail::initializer_str(itr->second);
ret += "}";
}
ret += "}";
return ret;
}
template <typename T1, typename T2>
inline std::string repr(const std::map<T1, T2>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
template <typename T, size_t N>
inline std::string type_str(const std::array<T, N>&) {
T t;
return "std::array<" + detail::type_str(t) + ", " + std::to_string(N) + ">";
}
template <typename T, size_t N>
inline std::string initializer_str(const std::array<T, N>& t) {
std::string ret;
ret += "{";
for (auto itr = t.begin(); itr != t.end(); itr++) {
if (itr != t.begin()) ret += ", ";
ret += detail::initializer_str(*itr);
}
ret += "}";
return ret;
}
template <typename T, size_t N>
inline std::string repr(const std::array<T, N>& t) {
return detail::type_str(t) + detail::initializer_str(t);
}
} // namespace detail
template <typename T>
inline std::string type_str(const T& t) {
return detail::type_str(t);
}
template <typename T>
inline std::string initializer_str(const T& t) {
return detail::initializer_str(t);
}
template <typename T>
inline std::string repr(const T& t) {
return detail::repr(t);
}
#define DEBUG(x) { std::cerr << #x << " = " << repr(x) << std::endl; }