几乎什么都能转。
把tuple转字符串最难写。
#include <bits/stdc++.h>
namespace ext {
template <typename StrType>
std::string ToString(const StrType& str);
template <typename StrType>
std::string ToString(const std::vector<StrType>& vec);
template <typename... Args>
std::string ToString(const std::tuple<Args...>& tpl);
template <typename K, typename D, typename A>
std::string ToString(const std::set<K, D, A>& value);
template <typename K, typename D, typename A>
std::string ToString(const std::multiset<K, D, A>& value);
template <typename K, typename H, typename D, typename A>
std::string ToString(const std::unordered_set<K, H, D, A>& value);
template <typename K, typename V, typename D, typename A>
std::string ToString(const std::map<K, V, D, A>& value);
template <typename K, typename V, typename D, typename A>
std::string ToString(const std::multimap<K, V, D, A>& value);
template <typename K, typename V, typename H, typename D, typename A>
std::string ToString(const std::unordered_map<K, V, H, D, A>& value);
template <typename... Args>
std::string ToString(const std::pair<Args...>& tpl);
std::string ToString(const std::string& value);
namespace detail {
template <typename Tuple, int pos>
struct ToStringImpl {
static std::string Impl(const Tuple& tpl) {
return ToStringImpl<Tuple, pos - 1>::Impl(tpl).append(ext::ToString(std::get<pos>(tpl))).append(pos + 1 == static_cast<int>(std::tuple_size_v<Tuple>) ? "" : ", ");
}
};
template <typename Tuple>
struct ToStringImpl<Tuple, -1> {
static std::string Impl(const Tuple& tpl) {
return std::string();
}
};
template <typename Tuple>
struct ToStringImpl<Tuple, 0> {
static std::string Impl(const Tuple& tpl) {
return ext::ToString(std::get<0>(tpl)).append(1 == static_cast<int>(std::tuple_size_v<Tuple>) ? "" : ", ");
}
};
template <typename SetType>
std::string ToStringSetImpl(const SetType& value) {
std::string res = "{";
for (typename SetType::const_iterator iter = value.begin(); iter != value.end(); iter++) {
if (iter != value.begin()) {
res.append(", ");
}
res.append(ToString(*iter));
}
return res.append("}");
}
template <typename MapType>
std::string ToStringMapImpl(const MapType& value) {
std::string res = "{";
for (typename MapType::const_iterator iter = value.begin(); iter != value.end(); iter++) {
if (iter != value.begin()) {
res.append(", ");
}
res.append(ToString(iter->first));
res.append(": ");
res.append(ToString(iter->second));
}
return res.append("}");
}
} // namespace detail
template <typename StrType>
std::string ToString(const StrType& str) {
std::ostringstream oss;
oss << str;
return oss.str();
}
template <typename StrType>
std::string ToString(const std::vector<StrType>& vec) {
std::string res = "[";
const int n = vec.size();
for (int i = 0; i < n; i++) {
res.append(ToString(vec[i])).append((i + 1 == n ? "" : ", "));
}
res.append("]");
return res;
}
template <typename... Args>
std::string ToString(const std::tuple<Args...>& tpl) {
std::string res = "(";
res.append(detail::ToStringImpl<std::tuple<Args...>, static_cast<int>(std::tuple_size_v<std::tuple<Args...>>) - 1>::Impl(tpl));
res.append(")");
return res;
}
template <typename K, typename D, typename A>
std::string ToString(const std::set<K, D, A>& value) {
return detail::ToStringSetImpl(value);
}
template <typename K, typename D, typename A>
std::string ToString(const std::multiset<K, D, A>& value) {
return detail::ToStringSetImpl(value);
}
template <typename K, typename H, typename D, typename A>
std::string ToString(const std::unordered_set<K, H, D, A>& value) {
return detail::ToStringSetImpl(value);
}
template <typename K, typename V, typename D, typename A>
std::string ToString(const std::map<K, V, D, A>& value) {
return detail::ToStringMapImpl(value);
}
template <typename K, typename V, typename D, typename A>
std::string ToString(const std::multimap<K, V, D, A>& value) {
return detail::ToStringMapImpl(value);
}
template <typename K, typename V, typename H, typename D, typename A>
std::string ToString(const std::unordered_map<K, V, H, D, A>& value) {
return detail::ToStringMapImpl(value);
}
template <typename... Args>
std::string ToString(const std::pair<Args...>& tpl) {
std::string res = "(";
res.append(detail::ToStringImpl<std::pair<Args...>, 1>::Impl(tpl));
res.append(")");
return res;
}
std::string ToString(const std::string& value) {
return value;
}
void Debug() {
std::cerr << '\n';
}
template <typename Head, typename... Tail>
void Debug(const Head& head, const Tail&... tail) {
std::cerr << " " << ToString(head);
Debug(tail...);
}
} // namespace ext
#ifdef local
#define DEBUG(...) do { std::cerr << "[" << #__VA_ARGS__ << "]:"; ext::Debug(__VA_ARGS__); } while (0)
#else
#define DEBUG(...) do { } while (0)
#endif
int main() {
std::cout << ext::ToString(std::vector<std::vector<int>>({{1, 2}, {2}})) << "\n";
std::cout << ext::ToString(std::make_tuple<int, int, std::string>(1, 2, "-")) << "\n";
std::cout << ext::ToString(std::make_tuple(1, std::make_tuple(2))) << '\n';
std::cout << ext::ToString(std::make_tuple()) << '\n';
std::cout << ext::ToString(std::map<int, std::tuple<int, int>> ({{1, {1, 1}}, {2, {-1, 1}}})) << '\n';
std::cout << ext::ToString(std::make_pair(1, std::make_tuple(1, 3))) << '\n';
std::cout << ext::ToString(std::unordered_set<int> ({1, 2, 3, 4})) << '\n';
DEBUG(1, std::make_pair(1, 2), std::make_pair(1, std::make_tuple(1, "3")));
} 
京公网安备 11010502036488号