#include <iostream>
#include <iterator>
#include <type_traits>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <tuple>
#include <list>
#include <sstream>
// This works similar to ostream_iterator, but doesn't print a delimiter after the final item
template <typename T, typename TChar = char, typename TCharTraits = std::char_traits<TChar>>
class pretty_ostream_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
typedef TChar char_type;
typedef TCharTraits traits_type;
typedef std::basic_ostream<TChar, TCharTraits> ostream_type;
pretty_ostream_iterator(ostream_type &stream, const char_type *delim = NULL)
: _stream(&stream), _delim(delim), _insertDelim(false)
{
}
pretty_ostream_iterator<T, TChar, TCharTraits> &operator=(const T &value)
{
if (_delim != NULL)
{
// Don't insert a delimiter if this is the first time the function is called
if (_insertDelim)
(*_stream) << _delim;
else
_insertDelim = true;
}
(*_stream) << value;
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits> &operator*()
{
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits> &operator++()
{
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits> &operator++(int)
{
return *this;
}
private:
ostream_type *_stream;
const char_type *_delim;
bool _insertDelim;
};
// Basic is_container template; specialize to derive from std::true_type for all desired container types
template <typename T>
struct is_container : public std::false_type
{
};
// Mark vector as a container
template <typename T, typename TAllocator>
struct is_container<std::vector<T, TAllocator>> : public std::true_type
{
};
// Mark list as a container
template <typename T, typename TAllocator>
struct is_container<std::list<T, TAllocator>> : public std::true_type
{
};
// Mark set as a container
template <typename T, typename TTraits, typename TAllocator>
struct is_container<std::set<T, TTraits, TAllocator>> : public std::true_type
{
};
// Mark map as a container
template <typename TKey, typename TValue, typename TTraits, typename TAllocator>
struct is_container<std::map<TKey, TValue, TTraits, TAllocator>> : public std::true_type
{
};
// Holds the delimiter values for a specific character type
template <typename TChar>
struct delimiters_values
{
typedef TChar char_type;
const TChar *prefix;
const TChar *delimiter;
const TChar *postfix;
};
// Defines the delimiter values for a specific container and character type
template <typename T, typename TChar>
struct delimiters
{
static const delimiters_values<TChar> values;
};
// Default delimiters
template <typename T>
struct delimiters<T, char>
{
static const delimiters_values<char> values;
};
template <typename T>
const delimiters_values<char> delimiters<T, char>::values = {"[", ", ", "]"};
template <typename T>
struct delimiters<T, wchar_t>
{
static const delimiters_values<wchar_t> values;
};
template <typename T>
const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = {L"[", L", ", L"]"};
// Delimiters for set
template <typename T, typename TTraits, typename TAllocator>
struct delimiters<std::set<T, TTraits, TAllocator>, char>
{
static const delimiters_values<char> values;
};
template <typename T, typename TTraits, typename TAllocator>
const delimiters_values<char> delimiters<std::set<T, TTraits, TAllocator>, char>::values = {"[", ", ", "]"};
template <typename T, typename TTraits, typename TAllocator>
struct delimiters<std::set<T, TTraits, TAllocator>, wchar_t>
{
static const delimiters_values<wchar_t> values;
};
template <typename T, typename TTraits, typename TAllocator>
const delimiters_values<wchar_t> delimiters<std::set<T, TTraits, TAllocator>, wchar_t>::values = {L"[", L", ", L"]"};
// Delimiters for pair
template <typename T1, typename T2>
struct delimiters<std::pair<T1, T2>, char>
{
static const delimiters_values<char> values;
};
template <typename T1, typename T2>
const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = {"{", ": ", "}"};
template <typename T1, typename T2>
struct delimiters<std::pair<T1, T2>, wchar_t>
{
static const delimiters_values<wchar_t> values;
};
template <typename T1, typename T2>
const delimiters_values<wchar_t> delimiters<std::pair<T1, T2>, wchar_t>::values = {L"{", L": ", L"}"};
// Functor to print containers. You can use this directly if you want to specificy a non-default delimiters type.
template <typename T, typename TChar = char, typename TCharTraits = std::char_traits<TChar>, typename TDelimiters = delimiters<T, TChar>>
struct print_container_helper
{
typedef TChar char_type;
typedef TDelimiters delimiters_type;
typedef std::basic_ostream<TChar, TCharTraits> &ostream_type;
print_container_helper(const T &container)
: _container(&container)
{
}
void operator()(ostream_type &stream) const
{
if (delimiters_type::values.prefix != NULL)
stream << delimiters_type::values.prefix;
std::copy(_container->begin(), _container->end(), pretty_ostream_iterator<typename T::value_type, TChar, TCharTraits>(stream, delimiters_type::values.delimiter));
if (delimiters_type::values.postfix != NULL)
stream << delimiters_type::values.postfix;
}
private:
const T *_container;
};
// Prints a print_container_helper to the specified stream.
template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
std::basic_ostream<TChar, TCharTraits> &operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const print_container_helper<T, TChar, TDelimiters> &helper)
{
helper(stream);
return stream;
}
// Prints a container to the stream using default delimiters
template <typename T, typename TChar, typename TCharTraits>
typename std::enable_if<is_container<T>::value, std::basic_ostream<TChar, TCharTraits> &>::type
operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const T &container)
{
stream << print_container_helper<T, TChar, TCharTraits>(container);
return stream;
}
// Prints a pair to the stream using delimiters from delimiters<std::pair<T1, T2>>.
template <typename T1, typename T2, typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> &operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const std::pair<T1, T2> &value)
{
if (delimiters<std::pair<T1, T2>, TChar>::values.prefix != NULL)
stream << delimiters<std::pair<T1, T2>, TChar>::values.prefix;
stream << value.first;
if (delimiters<std::pair<T1, T2>, TChar>::values.delimiter != NULL)
stream << delimiters<std::pair<T1, T2>, TChar>::values.delimiter;
stream << value.second;
if (delimiters<std::pair<T1, T2>, TChar>::values.postfix != NULL)
stream << delimiters<std::pair<T1, T2>, TChar>::values.postfix;
return stream;
}
template <typename T1>
std::string j_encode(const T1 &target)
{
std::stringstream buf;
buf << target;
return buf.str();
}
#include "./jencode.hpp"
int main()
{
std::vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// printf("%s\n", j_encode(a).c_str());
std::cout << a << std::endl;
std::set<int> b = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// printf("%s\n", j_encode(a).c_str());
std::cout << b << std::endl;
std::string s = "fdfasdas";
// printf("%s\n", j_encode(a).c_str());
std::cout << s << std::endl;
std::map<int, int> m1;
m1[1] = 1;
m1[2] = 2;
m1[3] = 3;
// printf("%s\n", j_encode(a).c_str());
std::cout << m1 << std::endl;
std::map<int, std::map<int, std::vector<std::string>>> m2;
m2[1][2] = {"abc", "def"};
m2[2][2] = {"ab", "de"};
// printf("%s\n", j_encode(a).c_str());
std::cout << m2 << std::endl;
std::pair<int, std::vector<std::string>> pr = std::make_pair<int, std::vector<std::string>>(2, {"sdsada", "fdsad"});
// printf("%s\n", j_encode(a).c_str());
std::cout << pr << std::endl;
return 0;
打印结果
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
fdfasdas
[{1: 1}, {2: 2}, {3: 3}]
[{1: [{2: [abc, def]}]}, {2: [{2: [ab, de]}]}]
{2: [sdsada, fdsad]}