shogo-library

競技プログラミング用の C++ ライブラリ

View the Project on GitHub shogo314/shogo-library

:heavy_check_mark: 出力をそのままコンストラクタに使える文字列化 (repr)
(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() を定義すれば対応できます。

Depends on

Verified with

Code

#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; }
Back to top page