algo

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub dnx04/algo

:warning: misc/prettyprint.hpp

Code

//          Copyright Louis Delacroix 2010 - 2014.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)
//
// A pretty printing library for C++
//
// Usage:
// Include this header, and operator<< will "just work".

#ifndef H_PRETTY_PRINT
#define H_PRETTY_PRINT

#include <cstddef>
#include <iterator>
#include <memory>
#include <ostream>
#include <set>
#include <tuple>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <valarray>

namespace pretty_print {
namespace detail {
// SFINAE type trait to detect whether T::const_iterator exists.

struct sfinae_base {
  using yes = char;
  using no = yes[2];
};

template <typename T>
struct has_const_iterator : private sfinae_base {
 private:
  template <typename C>
  static yes& test(typename C::const_iterator*);
  template <typename C>
  static no& test(...);

 public:
  static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
  using type = T;
};

template <typename T>
struct has_begin_end : private sfinae_base {
 private:
  template <typename C>
  static yes& f(typename std::enable_if<
                std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::begin)),
                             typename C::const_iterator (C::*)() const>::value>::type*);

  template <typename C>
  static no& f(...);

  template <typename C>
  static yes& g(typename std::enable_if<
                std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::end)),
                             typename C::const_iterator (C::*)() const>::value,
                void>::type*);

  template <typename C>
  static no& g(...);

 public:
  static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
  static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
};

}  // namespace detail

// Holds the delimiter values for a specific character type

template <typename TChar>
struct delimiters_values {
  using char_type = TChar;
  const char_type* prefix;
  const char_type* delimiter;
  const char_type* postfix;
};

// Defines the delimiter values for a specific container and character type

template <typename T, typename TChar>
struct delimiters {
  using type = delimiters_values<TChar>;
  static const type values;
};

// Functor to print containers. You can use this directly if you want
// to specificy a non-default delimiters type. The printing logic can
// be customized by specializing the nested template.

template <typename T,
          typename TChar = char,
          typename TCharTraits = ::std::char_traits<TChar>,
          typename TDelimiters = delimiters<T, TChar>>
struct print_container_helper {
  using delimiters_type = TDelimiters;
  using ostream_type = std::basic_ostream<TChar, TCharTraits>;

  template <typename U>
  struct printer {
    static void print_body(const U& c, ostream_type& stream) {
      using std::begin;
      using std::end;

      auto it = begin(c);
      const auto the_end = end(c);

      if (it != the_end) {
        for (;;) {
          stream << *it;

          if (++it == the_end) break;

          if (delimiters_type::values.delimiter != NULL)
            stream << delimiters_type::values.delimiter;
        }
      }
    }
  };

  print_container_helper(const T& container)
      : container_(container) {}

  inline void operator()(ostream_type& stream) const {
    if (delimiters_type::values.prefix != NULL)
      stream << delimiters_type::values.prefix;

    printer<T>::print_body(container_, stream);

    if (delimiters_type::values.postfix != NULL)
      stream << delimiters_type::values.postfix;
  }

 private:
  const T& container_;
};

// Specialization for pairs

template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
template <typename T1, typename T2>
struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::pair<T1, T2>> {
  using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;

  static void print_body(const std::pair<T1, T2>& c, ostream_type& stream) {
    stream << c.first;
    if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
      stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
    stream << c.second;
  }
};

// Specialization for tuples

template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
template <typename... Args>
struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::tuple<Args...>> {
  using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
  using element_type = std::tuple<Args...>;

  template <std::size_t I>
  struct Int {};

  static void print_body(const element_type& c, ostream_type& stream) {
    tuple_print(c, stream, Int<0>());
  }

  static void tuple_print(const element_type&, ostream_type&, Int<sizeof...(Args)>) {
  }

  static void tuple_print(const element_type& c, ostream_type& stream,
                          typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type) {
    stream << std::get<0>(c);
    tuple_print(c, stream, Int<1>());
  }

  template <std::size_t N>
  static void tuple_print(const element_type& c, ostream_type& stream, Int<N>) {
    if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
      stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;

    stream << std::get<N>(c);

    tuple_print(c, stream, Int<N + 1>());
  }
};

// Prints a print_container_helper to the specified stream.

template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
inline std::basic_ostream<TChar, TCharTraits>& operator<<(
    std::basic_ostream<TChar, TCharTraits>& stream,
    const print_container_helper<T, TChar, TCharTraits, TDelimiters>& helper) {
  helper(stream);
  return stream;
}

// Basic is_container template; specialize to derive from std::true_type for all desired container types

template <typename T>
struct is_container : public std::integral_constant<bool,
                                                    detail::has_const_iterator<T>::value &&
                                                        detail::has_begin_end<T>::beg_value &&
                                                        detail::has_begin_end<T>::end_value> {};

template <typename T, std::size_t N>
struct is_container<T[N]> : std::true_type {};

template <std::size_t N>
struct is_container<char[N]> : std::false_type {};

template <typename T>
struct is_container<std::valarray<T>> : std::true_type {};

template <typename T1, typename T2>
struct is_container<std::pair<T1, T2>> : std::true_type {};

template <typename... Args>
struct is_container<std::tuple<Args...>> : std::true_type {};

// 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 (multi)set and unordered_(multi)set

template <typename T, typename TComp, typename TAllocator>
struct delimiters<::std::set<T, TComp, TAllocator>, char> {
  static const delimiters_values<char> values;
};

template <typename T, typename TComp, typename TAllocator>
const delimiters_values<char> delimiters<::std::set<T, TComp, TAllocator>, char>::values = {"{", ", ", "}"};

template <typename T, typename TComp, typename TAllocator>
struct delimiters<::std::set<T, TComp, TAllocator>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template <typename T, typename TComp, typename TAllocator>
const delimiters_values<wchar_t> delimiters<::std::set<T, TComp, TAllocator>, wchar_t>::values = {L"{", L", ", L"}"};

template <typename T, typename TComp, typename TAllocator>
struct delimiters<::std::multiset<T, TComp, TAllocator>, char> {
  static const delimiters_values<char> values;
};

template <typename T, typename TComp, typename TAllocator>
const delimiters_values<char> delimiters<::std::multiset<T, TComp, TAllocator>, char>::values = {"{", ", ", "}"};

template <typename T, typename TComp, typename TAllocator>
struct delimiters<::std::multiset<T, TComp, TAllocator>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template <typename T, typename TComp, typename TAllocator>
const delimiters_values<wchar_t> delimiters<::std::multiset<T, TComp, TAllocator>, wchar_t>::values = {L"{", L", ", L"}"};

template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, char> {
  static const delimiters_values<char> values;
};

template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<char> delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = {"{", ", ", "}"};

template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<wchar_t> delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = {L"{", L", ", L"}"};

template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, char> {
  static const delimiters_values<char> values;
};

template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<char> delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = {"{", ", ", "}"};

template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<wchar_t> delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = {L"{", L", ", L"}"};

// Delimiters for pair and tuple

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")"};

template <typename... Args>
struct delimiters<std::tuple<Args...>, char> {
  static const delimiters_values<char> values;
};
template <typename... Args>
const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values = {"(", ", ", ")"};
template <typename... Args>
struct delimiters<::std::tuple<Args...>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};
template <typename... Args>
const delimiters_values<wchar_t> delimiters<::std::tuple<Args...>, wchar_t>::values = {L"(", L", ", L")"};

// Type-erasing helper class for easy use of custom delimiters.
// Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
// Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".

struct custom_delims_base {
  virtual ~custom_delims_base() {}
  virtual std::ostream& stream(::std::ostream&) = 0;
  virtual std::wostream& stream(::std::wostream&) = 0;
};

template <typename T, typename Delims>
struct custom_delims_wrapper : custom_delims_base {
  custom_delims_wrapper(const T& t_) : t(t_) {}

  std::ostream& stream(std::ostream& s) {
    return s << print_container_helper<T, char, std::char_traits<char>, Delims>(t);
  }

  std::wostream& stream(std::wostream& s) {
    return s << print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t);
  }

 private:
  const T& t;
};

template <typename Delims>
struct custom_delims {
  template <typename Container>
  custom_delims(const Container& c) : base(new custom_delims_wrapper<Container, Delims>(c)) {}

  std::unique_ptr<custom_delims_base> base;
};

template <typename TChar, typename TCharTraits, typename Delims>
inline std::basic_ostream<TChar, TCharTraits>& operator<<(std::basic_ostream<TChar, TCharTraits>& s, const custom_delims<Delims>& p) {
  return p.base->stream(s);
}

// A wrapper for a C-style array given as pointer-plus-size.
// Usage: std::cout << pretty_print_array(arr, n) << std::endl;

template <typename T>
struct array_wrapper_n {
  typedef const T* const_iterator;
  typedef T value_type;

  array_wrapper_n(const T* const a, size_t n) : _array(a), _n(n) {}
  inline const_iterator begin() const { return _array; }
  inline const_iterator end() const { return _array + _n; }

 private:
  const T* const _array;
  size_t _n;
};

// A wrapper for hash-table based containers that offer local iterators to each bucket.
// Usage: std::cout << bucket_print(m, 4) << std::endl;  (Prints bucket 5 of container m.)

template <typename T>
struct bucket_print_wrapper {
  typedef typename T::const_local_iterator const_iterator;
  typedef typename T::size_type size_type;

  const_iterator begin() const {
    return m_map.cbegin(n);
  }

  const_iterator end() const {
    return m_map.cend(n);
  }

  bucket_print_wrapper(const T& m, size_type bucket) : m_map(m), n(bucket) {}

 private:
  const T& m_map;
  const size_type n;
};

}  // namespace pretty_print

// Global accessor functions for the convenience wrappers

template <typename T>
inline pretty_print::array_wrapper_n<T> pretty_print_array(const T* const a, size_t n) {
  return pretty_print::array_wrapper_n<T>(a, n);
}

template <typename T>
pretty_print::bucket_print_wrapper<T>
bucket_print(const T& m, typename T::size_type n) {
  return pretty_print::bucket_print_wrapper<T>(m, n);
}

// Main magic entry point: An overload snuck into namespace std.
// Can we do better?

namespace std {
// Prints a container to the stream using default delimiters

template <typename T, typename TChar, typename TCharTraits>
inline typename enable_if<::pretty_print::is_container<T>::value,
                          basic_ostream<TChar, TCharTraits>&>::type
operator<<(basic_ostream<TChar, TCharTraits>& stream, const T& container) {
  return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
}
}  // namespace std

#endif  // H_PRETTY_PRINT
#line 1 "misc/prettyprint.hpp"
//          Copyright Louis Delacroix 2010 - 2014.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)
//
// A pretty printing library for C++
//
// Usage:
// Include this header, and operator<< will "just work".

#ifndef H_PRETTY_PRINT
#define H_PRETTY_PRINT

#include <cstddef>
#include <iterator>
#include <memory>
#include <ostream>
#include <set>
#include <tuple>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <valarray>

namespace pretty_print {
namespace detail {
// SFINAE type trait to detect whether T::const_iterator exists.

struct sfinae_base {
  using yes = char;
  using no = yes[2];
};

template <typename T>
struct has_const_iterator : private sfinae_base {
 private:
  template <typename C>
  static yes& test(typename C::const_iterator*);
  template <typename C>
  static no& test(...);

 public:
  static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
  using type = T;
};

template <typename T>
struct has_begin_end : private sfinae_base {
 private:
  template <typename C>
  static yes& f(typename std::enable_if<
                std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::begin)),
                             typename C::const_iterator (C::*)() const>::value>::type*);

  template <typename C>
  static no& f(...);

  template <typename C>
  static yes& g(typename std::enable_if<
                std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::end)),
                             typename C::const_iterator (C::*)() const>::value,
                void>::type*);

  template <typename C>
  static no& g(...);

 public:
  static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
  static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
};

}  // namespace detail

// Holds the delimiter values for a specific character type

template <typename TChar>
struct delimiters_values {
  using char_type = TChar;
  const char_type* prefix;
  const char_type* delimiter;
  const char_type* postfix;
};

// Defines the delimiter values for a specific container and character type

template <typename T, typename TChar>
struct delimiters {
  using type = delimiters_values<TChar>;
  static const type values;
};

// Functor to print containers. You can use this directly if you want
// to specificy a non-default delimiters type. The printing logic can
// be customized by specializing the nested template.

template <typename T,
          typename TChar = char,
          typename TCharTraits = ::std::char_traits<TChar>,
          typename TDelimiters = delimiters<T, TChar>>
struct print_container_helper {
  using delimiters_type = TDelimiters;
  using ostream_type = std::basic_ostream<TChar, TCharTraits>;

  template <typename U>
  struct printer {
    static void print_body(const U& c, ostream_type& stream) {
      using std::begin;
      using std::end;

      auto it = begin(c);
      const auto the_end = end(c);

      if (it != the_end) {
        for (;;) {
          stream << *it;

          if (++it == the_end) break;

          if (delimiters_type::values.delimiter != NULL)
            stream << delimiters_type::values.delimiter;
        }
      }
    }
  };

  print_container_helper(const T& container)
      : container_(container) {}

  inline void operator()(ostream_type& stream) const {
    if (delimiters_type::values.prefix != NULL)
      stream << delimiters_type::values.prefix;

    printer<T>::print_body(container_, stream);

    if (delimiters_type::values.postfix != NULL)
      stream << delimiters_type::values.postfix;
  }

 private:
  const T& container_;
};

// Specialization for pairs

template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
template <typename T1, typename T2>
struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::pair<T1, T2>> {
  using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;

  static void print_body(const std::pair<T1, T2>& c, ostream_type& stream) {
    stream << c.first;
    if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
      stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
    stream << c.second;
  }
};

// Specialization for tuples

template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
template <typename... Args>
struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::tuple<Args...>> {
  using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
  using element_type = std::tuple<Args...>;

  template <std::size_t I>
  struct Int {};

  static void print_body(const element_type& c, ostream_type& stream) {
    tuple_print(c, stream, Int<0>());
  }

  static void tuple_print(const element_type&, ostream_type&, Int<sizeof...(Args)>) {
  }

  static void tuple_print(const element_type& c, ostream_type& stream,
                          typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type) {
    stream << std::get<0>(c);
    tuple_print(c, stream, Int<1>());
  }

  template <std::size_t N>
  static void tuple_print(const element_type& c, ostream_type& stream, Int<N>) {
    if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
      stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;

    stream << std::get<N>(c);

    tuple_print(c, stream, Int<N + 1>());
  }
};

// Prints a print_container_helper to the specified stream.

template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
inline std::basic_ostream<TChar, TCharTraits>& operator<<(
    std::basic_ostream<TChar, TCharTraits>& stream,
    const print_container_helper<T, TChar, TCharTraits, TDelimiters>& helper) {
  helper(stream);
  return stream;
}

// Basic is_container template; specialize to derive from std::true_type for all desired container types

template <typename T>
struct is_container : public std::integral_constant<bool,
                                                    detail::has_const_iterator<T>::value &&
                                                        detail::has_begin_end<T>::beg_value &&
                                                        detail::has_begin_end<T>::end_value> {};

template <typename T, std::size_t N>
struct is_container<T[N]> : std::true_type {};

template <std::size_t N>
struct is_container<char[N]> : std::false_type {};

template <typename T>
struct is_container<std::valarray<T>> : std::true_type {};

template <typename T1, typename T2>
struct is_container<std::pair<T1, T2>> : std::true_type {};

template <typename... Args>
struct is_container<std::tuple<Args...>> : std::true_type {};

// 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 (multi)set and unordered_(multi)set

template <typename T, typename TComp, typename TAllocator>
struct delimiters<::std::set<T, TComp, TAllocator>, char> {
  static const delimiters_values<char> values;
};

template <typename T, typename TComp, typename TAllocator>
const delimiters_values<char> delimiters<::std::set<T, TComp, TAllocator>, char>::values = {"{", ", ", "}"};

template <typename T, typename TComp, typename TAllocator>
struct delimiters<::std::set<T, TComp, TAllocator>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template <typename T, typename TComp, typename TAllocator>
const delimiters_values<wchar_t> delimiters<::std::set<T, TComp, TAllocator>, wchar_t>::values = {L"{", L", ", L"}"};

template <typename T, typename TComp, typename TAllocator>
struct delimiters<::std::multiset<T, TComp, TAllocator>, char> {
  static const delimiters_values<char> values;
};

template <typename T, typename TComp, typename TAllocator>
const delimiters_values<char> delimiters<::std::multiset<T, TComp, TAllocator>, char>::values = {"{", ", ", "}"};

template <typename T, typename TComp, typename TAllocator>
struct delimiters<::std::multiset<T, TComp, TAllocator>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template <typename T, typename TComp, typename TAllocator>
const delimiters_values<wchar_t> delimiters<::std::multiset<T, TComp, TAllocator>, wchar_t>::values = {L"{", L", ", L"}"};

template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, char> {
  static const delimiters_values<char> values;
};

template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<char> delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = {"{", ", ", "}"};

template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<wchar_t> delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = {L"{", L", ", L"}"};

template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, char> {
  static const delimiters_values<char> values;
};

template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<char> delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = {"{", ", ", "}"};

template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<wchar_t> delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = {L"{", L", ", L"}"};

// Delimiters for pair and tuple

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")"};

template <typename... Args>
struct delimiters<std::tuple<Args...>, char> {
  static const delimiters_values<char> values;
};
template <typename... Args>
const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values = {"(", ", ", ")"};
template <typename... Args>
struct delimiters<::std::tuple<Args...>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};
template <typename... Args>
const delimiters_values<wchar_t> delimiters<::std::tuple<Args...>, wchar_t>::values = {L"(", L", ", L")"};

// Type-erasing helper class for easy use of custom delimiters.
// Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
// Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".

struct custom_delims_base {
  virtual ~custom_delims_base() {}
  virtual std::ostream& stream(::std::ostream&) = 0;
  virtual std::wostream& stream(::std::wostream&) = 0;
};

template <typename T, typename Delims>
struct custom_delims_wrapper : custom_delims_base {
  custom_delims_wrapper(const T& t_) : t(t_) {}

  std::ostream& stream(std::ostream& s) {
    return s << print_container_helper<T, char, std::char_traits<char>, Delims>(t);
  }

  std::wostream& stream(std::wostream& s) {
    return s << print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t);
  }

 private:
  const T& t;
};

template <typename Delims>
struct custom_delims {
  template <typename Container>
  custom_delims(const Container& c) : base(new custom_delims_wrapper<Container, Delims>(c)) {}

  std::unique_ptr<custom_delims_base> base;
};

template <typename TChar, typename TCharTraits, typename Delims>
inline std::basic_ostream<TChar, TCharTraits>& operator<<(std::basic_ostream<TChar, TCharTraits>& s, const custom_delims<Delims>& p) {
  return p.base->stream(s);
}

// A wrapper for a C-style array given as pointer-plus-size.
// Usage: std::cout << pretty_print_array(arr, n) << std::endl;

template <typename T>
struct array_wrapper_n {
  typedef const T* const_iterator;
  typedef T value_type;

  array_wrapper_n(const T* const a, size_t n) : _array(a), _n(n) {}
  inline const_iterator begin() const { return _array; }
  inline const_iterator end() const { return _array + _n; }

 private:
  const T* const _array;
  size_t _n;
};

// A wrapper for hash-table based containers that offer local iterators to each bucket.
// Usage: std::cout << bucket_print(m, 4) << std::endl;  (Prints bucket 5 of container m.)

template <typename T>
struct bucket_print_wrapper {
  typedef typename T::const_local_iterator const_iterator;
  typedef typename T::size_type size_type;

  const_iterator begin() const {
    return m_map.cbegin(n);
  }

  const_iterator end() const {
    return m_map.cend(n);
  }

  bucket_print_wrapper(const T& m, size_type bucket) : m_map(m), n(bucket) {}

 private:
  const T& m_map;
  const size_type n;
};

}  // namespace pretty_print

// Global accessor functions for the convenience wrappers

template <typename T>
inline pretty_print::array_wrapper_n<T> pretty_print_array(const T* const a, size_t n) {
  return pretty_print::array_wrapper_n<T>(a, n);
}

template <typename T>
pretty_print::bucket_print_wrapper<T>
bucket_print(const T& m, typename T::size_type n) {
  return pretty_print::bucket_print_wrapper<T>(m, n);
}

// Main magic entry point: An overload snuck into namespace std.
// Can we do better?

namespace std {
// Prints a container to the stream using default delimiters

template <typename T, typename TChar, typename TCharTraits>
inline typename enable_if<::pretty_print::is_container<T>::value,
                          basic_ostream<TChar, TCharTraits>&>::type
operator<<(basic_ostream<TChar, TCharTraits>& stream, const T& container) {
  return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
}
}  // namespace std

#endif  // H_PRETTY_PRINT
Back to top page