run clang-format
This commit is contained in:
		
							parent
							
								
									4d25fc25c4
								
							
						
					
					
						commit
						492a0f3c55
					
				|  | @ -23,400 +23,446 @@ | ||||||
| 
 | 
 | ||||||
| namespace soi { | namespace soi { | ||||||
| 
 | 
 | ||||||
| template<typename T, typename TChar, typename TCharTraits> | template <typename T, typename TChar, typename TCharTraits> | ||||||
| std::basic_ostream<TChar, TCharTraits> & | std::basic_ostream<TChar, TCharTraits> & | ||||||
| print(std::basic_ostream<TChar, TCharTraits> & stream, const T& x); | print(std::basic_ostream<TChar, TCharTraits> &stream, const T &x); | ||||||
| 
 | 
 | ||||||
| namespace detail | namespace detail { | ||||||
| { |  | ||||||
| // SFINAE type trait to detect whether T::const_iterator exists.
 | // SFINAE type trait to detect whether T::const_iterator exists.
 | ||||||
| 
 | 
 | ||||||
| struct sfinae_base | struct sfinae_base { | ||||||
| { |   using yes = char; | ||||||
|     using yes = char; |   using no = yes[2]; | ||||||
|     using no  = yes[2]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> struct has_const_iterator : private sfinae_base { | ||||||
| struct has_const_iterator : private sfinae_base |  | ||||||
| { |  | ||||||
| private: | private: | ||||||
|     template <typename C> static yes & test(typename C::const_iterator*); |   template <typename C> static yes &test(typename C::const_iterator *); | ||||||
|     template <typename C> static no  & test(...); |   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: | public: | ||||||
|     static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes); |   static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes); | ||||||
|     static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes); |   using type = T; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| }  // namespace detail
 | 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
 | // Holds the delimiter values for a specific character type
 | ||||||
| 
 | 
 | ||||||
| template <typename TChar> | template <typename TChar> struct delimiters_values { | ||||||
| struct delimiters_values |   using char_type = TChar; | ||||||
| { |   const char_type *prefix; | ||||||
|     using char_type = TChar; |   const char_type *delimiter; | ||||||
|     const char_type * prefix; |   const char_type *postfix; | ||||||
|     const char_type * delimiter; |  | ||||||
|     const char_type * postfix; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| // Defines the delimiter values for a specific container and character type
 | // Defines the delimiter values for a specific container and character type
 | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TChar> | template <typename T, typename TChar> struct delimiters { | ||||||
| struct delimiters |   using type = delimiters_values<TChar>; | ||||||
| { |   static const type values; | ||||||
|     using type = delimiters_values<TChar>; |  | ||||||
|     static const type values; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| // Functor to pretty_print containers. You can use this directly if you want
 | // Functor to pretty_print containers. You can use this directly if you want
 | ||||||
| // to specificy a non-default delimiters type. The pretty_printing logic can
 | // to specificy a non-default delimiters type. The pretty_printing logic can
 | ||||||
| // be customized by specializing the nested template.
 | // be customized by specializing the nested template.
 | ||||||
| 
 | 
 | ||||||
| template <typename T, | template <typename T, typename TChar = char, | ||||||
|           typename TChar = char, |  | ||||||
|           typename TCharTraits = ::std::char_traits<TChar>, |           typename TCharTraits = ::std::char_traits<TChar>, | ||||||
|           typename TDelimiters = delimiters<T, TChar>> |           typename TDelimiters = delimiters<T, TChar>> | ||||||
| struct pretty_print_container_helper | struct pretty_print_container_helper { | ||||||
| { |   using delimiters_type = TDelimiters; | ||||||
|     using delimiters_type = TDelimiters; |   using ostream_type = std::basic_ostream<TChar, TCharTraits>; | ||||||
|     using ostream_type = std::basic_ostream<TChar, TCharTraits>; |  | ||||||
| 
 | 
 | ||||||
|     template <typename U> |   template <typename U> struct pretty_printer { | ||||||
|     struct pretty_printer |     static void pretty_print_body(const U &c, ostream_type &stream) { | ||||||
|     { |       using std::begin; | ||||||
|         static void pretty_print_body(const U & c, ostream_type & stream) |       using std::end; | ||||||
|         { |  | ||||||
|             using std::begin; |  | ||||||
|             using std::end; |  | ||||||
| 
 | 
 | ||||||
|             auto it = begin(c); |       auto it = begin(c); | ||||||
|             const auto the_end = end(c); |       const auto the_end = end(c); | ||||||
| 
 | 
 | ||||||
|             if (it != the_end) |       if (it != the_end) { | ||||||
|                 { |         for (;;) { | ||||||
|                     for ( ; ; ) |           ::soi::print(stream, *it); | ||||||
|                         { |  | ||||||
|                             ::soi::print(stream, *it); |  | ||||||
| 
 | 
 | ||||||
|                             if (++it == the_end) break; |           if (++it == the_end) | ||||||
|  |             break; | ||||||
| 
 | 
 | ||||||
|                             if (delimiters_type::values.delimiter != NULL) |           if (delimiters_type::values.delimiter != NULL) | ||||||
|                                 ::soi::print(stream, delimiters_type::values.delimiter); |             ::soi::print(stream, delimiters_type::values.delimiter); | ||||||
|                         } |  | ||||||
|                 } |  | ||||||
|         } |         } | ||||||
|     }; |       } | ||||||
| 
 |  | ||||||
|     pretty_print_container_helper(const T & container) |  | ||||||
|         : container_(container) |  | ||||||
|     { } |  | ||||||
| 
 |  | ||||||
|     inline void operator()(ostream_type & stream) const |  | ||||||
|     { |  | ||||||
|         if (delimiters_type::values.prefix != NULL) |  | ||||||
|             ::soi::print(stream, delimiters_type::values.prefix); |  | ||||||
| 
 |  | ||||||
|         pretty_printer<T>::pretty_print_body(container_, stream); |  | ||||||
| 
 |  | ||||||
|         if (delimiters_type::values.postfix != NULL) |  | ||||||
|             ::soi::print(stream, delimiters_type::values.postfix); |  | ||||||
|     } |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   pretty_print_container_helper(const T &container) : container_(container) {} | ||||||
|  | 
 | ||||||
|  |   inline void operator()(ostream_type &stream) const { | ||||||
|  |     if (delimiters_type::values.prefix != NULL) | ||||||
|  |       ::soi::print(stream, delimiters_type::values.prefix); | ||||||
|  | 
 | ||||||
|  |     pretty_printer<T>::pretty_print_body(container_, stream); | ||||||
|  | 
 | ||||||
|  |     if (delimiters_type::values.postfix != NULL) | ||||||
|  |       ::soi::print(stream, delimiters_type::values.postfix); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     const T & container_; |   const T &container_; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Specialization for pairs
 | // Specialization for pairs
 | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TChar, typename TCharTraits, typename TDelimiters> | template <typename T, typename TChar, typename TCharTraits, | ||||||
|  |           typename TDelimiters> | ||||||
| template <typename T1, typename T2> | template <typename T1, typename T2> | ||||||
| struct pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::pretty_printer<std::pair<T1, T2>> | struct pretty_print_container_helper< | ||||||
| { |     T, TChar, TCharTraits, TDelimiters>::pretty_printer<std::pair<T1, T2>> { | ||||||
|     using ostream_type = typename pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type; |   using ostream_type = | ||||||
|  |       typename pretty_print_container_helper<T, TChar, TCharTraits, | ||||||
|  |                                              TDelimiters>::ostream_type; | ||||||
| 
 | 
 | ||||||
|     static void pretty_print_body(const std::pair<T1, T2> & c, ostream_type & stream) |   static void pretty_print_body(const std::pair<T1, T2> &c, | ||||||
|     { |                                 ostream_type &stream) { | ||||||
|         ::soi::print(stream, c.first); |     ::soi::print(stream, c.first); | ||||||
|         if (pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL) |     if (pretty_print_container_helper<T, TChar, TCharTraits, | ||||||
|             ::soi::print(stream, pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter); |                                       TDelimiters>::delimiters_type::values | ||||||
|         ::soi::print(stream, c.second); |             .delimiter != NULL) | ||||||
|     } |       ::soi::print( | ||||||
|  |           stream, | ||||||
|  |           pretty_print_container_helper<T, TChar, TCharTraits, | ||||||
|  |                                         TDelimiters>::delimiters_type::values | ||||||
|  |               .delimiter); | ||||||
|  |     ::soi::print(stream, c.second); | ||||||
|  |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Specialization for tuples
 | // Specialization for tuples
 | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TChar, typename TCharTraits, typename TDelimiters> | template <typename T, typename TChar, typename TCharTraits, | ||||||
| template <typename ...Args> |           typename TDelimiters> | ||||||
| struct pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::pretty_printer<std::tuple<Args...>> | template <typename... Args> | ||||||
| { | struct pretty_print_container_helper< | ||||||
|     using ostream_type = typename pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type; |     T, TChar, TCharTraits, TDelimiters>::pretty_printer<std::tuple<Args...>> { | ||||||
|     using element_type = std::tuple<Args...>; |   using ostream_type = | ||||||
|  |       typename pretty_print_container_helper<T, TChar, TCharTraits, | ||||||
|  |                                              TDelimiters>::ostream_type; | ||||||
|  |   using element_type = std::tuple<Args...>; | ||||||
| 
 | 
 | ||||||
|     template <std::size_t I> struct Int { }; |   template <std::size_t I> struct Int {}; | ||||||
| 
 | 
 | ||||||
|     static void pretty_print_body(const element_type & c, ostream_type & stream) |   static void pretty_print_body(const element_type &c, ostream_type &stream) { | ||||||
|     { |     tuple_pretty_print(c, stream, Int<0>()); | ||||||
|         tuple_pretty_print(c, stream, Int<0>()); |   } | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     static void tuple_pretty_print(const element_type &, ostream_type &, Int<sizeof...(Args)>) |   static void tuple_pretty_print(const element_type &, ostream_type &, | ||||||
|     { |                                  Int<sizeof...(Args)>) {} | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     static void tuple_pretty_print(const element_type & c, ostream_type & stream, |   static void | ||||||
|                                    typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type) |   tuple_pretty_print(const element_type &c, ostream_type &stream, | ||||||
|     { |                      typename std::conditional<sizeof...(Args) != 0, Int<0>, | ||||||
|         ::soi::print(stream, std::get<0>(c)); |                                                std::nullptr_t>::type) { | ||||||
|         tuple_pretty_print(c, stream, Int<1>()); |     ::soi::print(stream, std::get<0>(c)); | ||||||
|     } |     tuple_pretty_print(c, stream, Int<1>()); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|     template <std::size_t N> |   template <std::size_t N> | ||||||
|     static void tuple_pretty_print(const element_type & c, ostream_type & stream, Int<N>) |   static void tuple_pretty_print(const element_type &c, ostream_type &stream, | ||||||
|     { |                                  Int<N>) { | ||||||
|         if (pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL) |     if (pretty_print_container_helper<T, TChar, TCharTraits, | ||||||
|             ::soi::print(stream, pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter); |                                       TDelimiters>::delimiters_type::values | ||||||
|  |             .delimiter != NULL) | ||||||
|  |       ::soi::print( | ||||||
|  |           stream, | ||||||
|  |           pretty_print_container_helper<T, TChar, TCharTraits, | ||||||
|  |                                         TDelimiters>::delimiters_type::values | ||||||
|  |               .delimiter); | ||||||
| 
 | 
 | ||||||
|         ::soi::print(stream, std::get<N>(c)); |     ::soi::print(stream, std::get<N>(c)); | ||||||
| 
 | 
 | ||||||
|         tuple_pretty_print(c, stream, Int<N + 1>()); |     tuple_pretty_print(c, stream, Int<N + 1>()); | ||||||
|     } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Pretty_Prints a pretty_print_container_helper to the specified stream.
 | // Pretty_Prints a pretty_print_container_helper to the specified stream.
 | ||||||
| 
 | 
 | ||||||
| template<typename T, typename TChar, typename TCharTraits, typename TDelimiters> | template <typename T, typename TChar, typename TCharTraits, | ||||||
| inline std::basic_ostream<TChar, TCharTraits> & pretty_print( |           typename TDelimiters> | ||||||
|                                                              std::basic_ostream<TChar, TCharTraits> & stream, | inline std::basic_ostream<TChar, TCharTraits> & | ||||||
|                                                              const pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper) | pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, | ||||||
| { |              const pretty_print_container_helper<T, TChar, TCharTraits, | ||||||
|     helper(stream); |                                                  TDelimiters> &helper) { | ||||||
|     return stream; |   helper(stream); | ||||||
|  |   return stream; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | // Basic is_container template; specialize to derive from std::true_type for all
 | ||||||
| // Basic is_container template; specialize to derive from std::true_type for all desired container types
 | // desired container types
 | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| struct is_container : public std::integral_constant<bool, | struct is_container | ||||||
|                                                     detail::has_const_iterator<T>::value && |     : public std::integral_constant<bool, | ||||||
|                                                     detail::has_begin_end<T>::beg_value  && |                                     detail::has_const_iterator<T>::value && | ||||||
|                                                     detail::has_begin_end<T>::end_value> { }; |                                         detail::has_begin_end<T>::beg_value && | ||||||
|  |                                         detail::has_begin_end<T>::end_value> {}; | ||||||
| 
 | 
 | ||||||
| template <typename T, std::size_t N> | template <typename T, std::size_t N> | ||||||
| struct is_container<T[N]> : std::true_type { }; | struct is_container<T[N]> : std::true_type {}; | ||||||
| 
 | 
 | ||||||
| template <std::size_t N> | template <std::size_t N> struct is_container<char[N]> : std::false_type {}; | ||||||
| struct is_container<char[N]> : std::false_type { }; |  | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> struct is_container<std::valarray<T>> : std::true_type {}; | ||||||
| struct is_container<std::valarray<T>> : std::true_type { }; |  | ||||||
| 
 | 
 | ||||||
| template <typename T1, typename T2> | template <typename T1, typename T2> | ||||||
| struct is_container<std::pair<T1, T2>> : std::true_type { }; | struct is_container<std::pair<T1, T2>> : std::true_type {}; | ||||||
| 
 |  | ||||||
| template <typename ...Args> |  | ||||||
| struct is_container<std::tuple<Args...>> : std::true_type { }; |  | ||||||
| 
 | 
 | ||||||
|  | template <typename... Args> | ||||||
|  | struct is_container<std::tuple<Args...>> : std::true_type {}; | ||||||
| 
 | 
 | ||||||
| // Default delimiters
 | // Default delimiters
 | ||||||
| 
 | 
 | ||||||
| template <typename T> struct delimiters<T, char> { static const delimiters_values<char> values; }; | template <typename T> struct delimiters<T, char> { | ||||||
| template <typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" }; |   static const delimiters_values<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"]" }; | 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
 | // Delimiters for (multi)set and unordered_(multi)set
 | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TComp, typename TAllocator> | template <typename T, typename TComp, typename TAllocator> | ||||||
| struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; }; | struct delimiters<::std::set<T, TComp, TAllocator>, char> { | ||||||
|  |   static const delimiters_values<char> values; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TComp, typename TAllocator> | template <typename T, typename TComp, typename TAllocator> | ||||||
| const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" }; | const delimiters_values<char> | ||||||
|  |     delimiters<::std::set<T, TComp, TAllocator>, char>::values = {"{", ", ", | ||||||
|  |                                                                   "}"}; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TComp, typename TAllocator> | template <typename T, typename TComp, typename TAllocator> | ||||||
| struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; }; | struct delimiters<::std::set<T, TComp, TAllocator>, wchar_t> { | ||||||
|  |   static const delimiters_values<wchar_t> values; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TComp, typename TAllocator> | template <typename T, typename TComp, typename TAllocator> | ||||||
| const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" }; | const delimiters_values<wchar_t> | ||||||
|  |     delimiters<::std::set<T, TComp, TAllocator>, wchar_t>::values = { | ||||||
|  |         L"{", L", ", L"}"}; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TComp, typename TAllocator> | template <typename T, typename TComp, typename TAllocator> | ||||||
| struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; }; | struct delimiters<::std::multiset<T, TComp, TAllocator>, char> { | ||||||
|  |   static const delimiters_values<char> values; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TComp, typename TAllocator> | template <typename T, typename TComp, typename TAllocator> | ||||||
| const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" }; | const delimiters_values<char> delimiters<::std::multiset<T, TComp, TAllocator>, | ||||||
|  |                                          char>::values = {"{", ", ", "}"}; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TComp, typename TAllocator> | template <typename T, typename TComp, typename TAllocator> | ||||||
| struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; }; | struct delimiters<::std::multiset<T, TComp, TAllocator>, wchar_t> { | ||||||
|  |   static const delimiters_values<wchar_t> values; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename TComp, typename TAllocator> | template <typename T, typename TComp, typename TAllocator> | ||||||
| const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" }; | 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> | 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; }; | 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> | template <typename T, typename THash, typename TEqual, typename TAllocator> | ||||||
| const delimiters_values<char> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" }; | const delimiters_values<char> delimiters< | ||||||
|  |     ::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { | ||||||
|  |     "{", ", ", "}"}; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename THash, typename TEqual, typename TAllocator> | 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; }; | 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> | 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"}" }; | 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> | 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; }; | 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> | template <typename T, typename THash, typename TEqual, typename TAllocator> | ||||||
| const delimiters_values<char> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" }; | const delimiters_values<char> delimiters< | ||||||
|  |     ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { | ||||||
|  |     "{", ", ", "}"}; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename THash, typename TEqual, typename TAllocator> | 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; }; | 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> | 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"}" }; | const delimiters_values<wchar_t> | ||||||
| 
 |     delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>, | ||||||
|  |                wchar_t>::values = {L"{", L", ", L"}"}; | ||||||
| 
 | 
 | ||||||
| // Delimiters for pair and tuple
 | // 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> struct delimiters<std::pair<T1, T2>, char> { | ||||||
| template <typename T1, typename T2> const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { "(", ", ", ")" }; |   static const delimiters_values<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 T1, typename T2> | ||||||
| 
 | const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { | ||||||
| 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 T1, typename T2> | ||||||
| template <typename ...Args> struct delimiters< ::std::tuple<Args...>, wchar_t> { static const delimiters_values<wchar_t> values; }; | struct delimiters<::std::pair<T1, T2>, wchar_t> { | ||||||
| template <typename ...Args> const delimiters_values<wchar_t> delimiters< ::std::tuple<Args...>, wchar_t>::values = { L"(", L", ", L")" }; |   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.
 | // 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.
 | // Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t,
 | ||||||
| // Usage: "cout << pretty_pretty_print::custom_delims<MyDelims>(x)".
 | // and MyDelims needs to be defined for TChar. Usage: "cout <<
 | ||||||
|  | // pretty_pretty_print::custom_delims<MyDelims>(x)".
 | ||||||
| 
 | 
 | ||||||
| struct custom_delims_base | struct custom_delims_base { | ||||||
| { |   virtual ~custom_delims_base() {} | ||||||
|     virtual ~custom_delims_base() { } |   virtual std::ostream &stream(::std::ostream &) = 0; | ||||||
|     virtual std::ostream & stream(::std::ostream &) = 0; |   virtual std::wostream &stream(::std::wostream &) = 0; | ||||||
|     virtual std::wostream & stream(::std::wostream &) = 0; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename T, typename Delims> | template <typename T, typename Delims> | ||||||
| struct custom_delims_wrapper : custom_delims_base | struct custom_delims_wrapper : custom_delims_base { | ||||||
| { |   custom_delims_wrapper(const T &t_) : t(t_) {} | ||||||
|     custom_delims_wrapper(const T & t_) : t(t_) { } |  | ||||||
| 
 | 
 | ||||||
|     std::ostream & stream(std::ostream & s) |   std::ostream &stream(std::ostream &s) { | ||||||
|     { |     return pretty_print( | ||||||
|         return pretty_print(s, pretty_print_container_helper<T, char, std::char_traits<char>, Delims>(t)); |         s, | ||||||
|     } |         pretty_print_container_helper<T, char, std::char_traits<char>, Delims>( | ||||||
|  |             t)); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|     std::wostream & stream(std::wostream & s) |   std::wostream &stream(std::wostream &s) { | ||||||
|     { |     return pretty_print( | ||||||
|         return pretty_print(s, pretty_print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t)); |         s, pretty_print_container_helper<T, wchar_t, std::char_traits<wchar_t>, | ||||||
|     } |                                          Delims>(t)); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     const T & t; |   const T &t; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename Delims> | template <typename Delims> struct custom_delims { | ||||||
| struct custom_delims |   template <typename Container> | ||||||
| { |   custom_delims(const Container &c) | ||||||
|     template <typename Container> |       : base(new custom_delims_wrapper<Container, Delims>(c)) {} | ||||||
|     custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { } |  | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<custom_delims_base> base; |   std::unique_ptr<custom_delims_base> base; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename TChar, typename TCharTraits, typename Delims> | template <typename TChar, typename TCharTraits, typename Delims> | ||||||
| inline std::basic_ostream<TChar, TCharTraits> & pretty_print(std::basic_ostream<TChar, TCharTraits> & s, const custom_delims<Delims> & p) | inline std::basic_ostream<TChar, TCharTraits> & | ||||||
| { | pretty_print(std::basic_ostream<TChar, TCharTraits> &s, | ||||||
|     return p.base->stream(s); |              const custom_delims<Delims> &p) { | ||||||
|  |   return p.base->stream(s); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| // A wrapper for a C-style array given as pointer-plus-size.
 | // A wrapper for a C-style array given as pointer-plus-size.
 | ||||||
| // Usage: std::cout << pretty_pretty_print_array(arr, n) << std::endl;
 | // Usage: std::cout << pretty_pretty_print_array(arr, n) << std::endl;
 | ||||||
| 
 | 
 | ||||||
| template<typename T> | template <typename T> struct array_wrapper_n { | ||||||
| struct array_wrapper_n |   typedef const T *const_iterator; | ||||||
| { |   typedef T value_type; | ||||||
|     typedef const T * const_iterator; |  | ||||||
|     typedef T value_type; |  | ||||||
| 
 | 
 | ||||||
|     array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { } |   array_wrapper_n(const T *const a, size_t n) : _array(a), _n(n) {} | ||||||
|     inline const_iterator begin() const { return _array; } |   inline const_iterator begin() const { return _array; } | ||||||
|     inline const_iterator end() const { return _array + _n; } |   inline const_iterator end() const { return _array + _n; } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     const T * const _array; |   const T *const _array; | ||||||
|     size_t _n; |   size_t _n; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // A wrapper for hash-table based containers that offer local iterators to each
 | ||||||
|  | // bucket. Usage: std::cout << bucket_pretty_print(m, 4) << std::endl;
 | ||||||
|  | // (Pretty_Prints bucket 5 of container m.)
 | ||||||
| 
 | 
 | ||||||
| // A wrapper for hash-table based containers that offer local iterators to each bucket.
 | template <typename T> struct bucket_pretty_print_wrapper { | ||||||
| // Usage: std::cout << bucket_pretty_print(m, 4) << std::endl;  (Pretty_Prints bucket 5 of container m.)
 |   typedef typename T::const_local_iterator const_iterator; | ||||||
|  |   typedef typename T::size_type size_type; | ||||||
| 
 | 
 | ||||||
| template <typename T> |   const_iterator begin() const { return m_map.cbegin(n); } | ||||||
| struct bucket_pretty_print_wrapper |  | ||||||
| { |  | ||||||
|     typedef typename T::const_local_iterator const_iterator; |  | ||||||
|     typedef typename T::size_type size_type; |  | ||||||
| 
 | 
 | ||||||
|     const_iterator begin() const |   const_iterator end() const { return m_map.cend(n); } | ||||||
|     { |  | ||||||
|         return m_map.cbegin(n); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     const_iterator end() const |   bucket_pretty_print_wrapper(const T &m, size_type bucket) | ||||||
|     { |       : m_map(m), n(bucket) {} | ||||||
|         return m_map.cend(n); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bucket_pretty_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { } |  | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     const T & m_map; |   const T &m_map; | ||||||
|     const size_type n; |   const size_type n; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| }   // namespace soi
 | } // namespace soi
 | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
| // Global accessor functions for the convenience wrappers
 | // Global accessor functions for the convenience wrappers
 | ||||||
| 
 | 
 | ||||||
| template<typename T> | template<typename T> | ||||||
| inline pretty_pretty_print::array_wrapper_n<T> pretty_pretty_print_array(const T * const a, size_t n) | inline pretty_pretty_print::array_wrapper_n<T> pretty_pretty_print_array(const T | ||||||
|  | * const a, size_t n) | ||||||
| { | { | ||||||
| return pretty_pretty_print::array_wrapper_n<T>(a, n); | return pretty_pretty_print::array_wrapper_n<T>(a, n); | ||||||
| } | } | ||||||
|  | @ -433,18 +479,18 @@ return pretty_pretty_print::bucket_pretty_print_wrapper<T>(m, n); | ||||||
| 
 | 
 | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| namespace soi | namespace soi { | ||||||
| { |  | ||||||
| // Pretty_Prints a container to the stream using default delimiters
 | // Pretty_Prints a container to the stream using default delimiters
 | ||||||
| 
 | 
 | ||||||
| template<typename T, typename TChar, typename TCharTraits> | template <typename T, typename TChar, typename TCharTraits> | ||||||
| inline typename std::enable_if< ::soi::is_container<T>::value, | inline typename std::enable_if<::soi::is_container<T>::value, | ||||||
|                                 std::basic_ostream<TChar, TCharTraits> &>::type |                                std::basic_ostream<TChar, TCharTraits> &>::type | ||||||
| pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const T & container) | pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, | ||||||
| { |              const T &container) { | ||||||
|     return ::soi::print(stream, ::soi::pretty_print_container_helper<T, TChar, TCharTraits>(container)); |   return ::soi::print( | ||||||
| } |       stream, | ||||||
|  |       ::soi::pretty_print_container_helper<T, TChar, TCharTraits>(container)); | ||||||
| } | } | ||||||
|  | } // namespace soi
 | ||||||
| 
 | 
 | ||||||
| 
 | #endif // SOI_PRETTY_PRETTY_PRINT
 | ||||||
| #endif  // SOI_PRETTY_PRETTY_PRINT
 |  | ||||||
|  |  | ||||||
|  | @ -11,11 +11,11 @@ | ||||||
| #define SOI_DBG | #define SOI_DBG | ||||||
| 
 | 
 | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include <stdexcept> |  | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <ostream> |  | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  | #include <ostream> | ||||||
| #include <sstream> | #include <sstream> | ||||||
|  | #include <stdexcept> | ||||||
| 
 | 
 | ||||||
| #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) | #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | @ -31,113 +31,99 @@ namespace detail { | ||||||
| // detecting the type name: https://stackoverflow.com/a/20170989
 | // detecting the type name: https://stackoverflow.com/a/20170989
 | ||||||
| 
 | 
 | ||||||
| #ifndef _MSC_VER | #ifndef _MSC_VER | ||||||
| #  if __cplusplus < 201103 | #if __cplusplus < 201103 | ||||||
| #    define CONSTEXPR11_TN | #define CONSTEXPR11_TN | ||||||
| #    define CONSTEXPR14_TN | #define CONSTEXPR14_TN | ||||||
| #    define NOEXCEPT_TN | #define NOEXCEPT_TN | ||||||
| #  elif __cplusplus < 201402 | #elif __cplusplus < 201402 | ||||||
| #    define CONSTEXPR11_TN constexpr | #define CONSTEXPR11_TN constexpr | ||||||
| #    define CONSTEXPR14_TN | #define CONSTEXPR14_TN | ||||||
| #    define NOEXCEPT_TN noexcept | #define NOEXCEPT_TN noexcept | ||||||
| #  else | #else | ||||||
| #    define CONSTEXPR11_TN constexpr | #define CONSTEXPR11_TN constexpr | ||||||
| #    define CONSTEXPR14_TN constexpr | #define CONSTEXPR14_TN constexpr | ||||||
| #    define NOEXCEPT_TN noexcept | #define NOEXCEPT_TN noexcept | ||||||
| #  endif | #endif | ||||||
| #else  // _MSC_VER
 | #else // _MSC_VER
 | ||||||
| #  if _MSC_VER < 1900 | #if _MSC_VER < 1900 | ||||||
| #    define CONSTEXPR11_TN | #define CONSTEXPR11_TN | ||||||
| #    define CONSTEXPR14_TN | #define CONSTEXPR14_TN | ||||||
| #    define NOEXCEPT_TN | #define NOEXCEPT_TN | ||||||
| #  elif _MSC_VER < 2000 | #elif _MSC_VER < 2000 | ||||||
| #    define CONSTEXPR11_TN constexpr | #define CONSTEXPR11_TN constexpr | ||||||
| #    define CONSTEXPR14_TN | #define CONSTEXPR14_TN | ||||||
| #    define NOEXCEPT_TN noexcept | #define NOEXCEPT_TN noexcept | ||||||
| #  else | #else | ||||||
| #    define CONSTEXPR11_TN constexpr | #define CONSTEXPR11_TN constexpr | ||||||
| #    define CONSTEXPR14_TN constexpr | #define CONSTEXPR14_TN constexpr | ||||||
| #    define NOEXCEPT_TN noexcept | #define NOEXCEPT_TN noexcept | ||||||
| #  endif | #endif | ||||||
| #endif  // _MSC_VER
 | #endif // _MSC_VER
 | ||||||
| 
 | 
 | ||||||
| class static_string { | class static_string { | ||||||
|     const char* const p_; |   const char *const p_; | ||||||
|     const std::size_t sz_; |   const std::size_t sz_; | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     typedef const char* const_iterator; |   typedef const char *const_iterator; | ||||||
| 
 | 
 | ||||||
|     template <std::size_t N> |   template <std::size_t N> | ||||||
|     CONSTEXPR11_TN static_string(const char(&a)[N]) NOEXCEPT_TN |   CONSTEXPR11_TN static_string(const char (&a)[N]) NOEXCEPT_TN : p_(a), | ||||||
|         : p_(a) |                                                                  sz_(N - 1) {} | ||||||
|         , sz_(N-1) |  | ||||||
|         {} |  | ||||||
| 
 | 
 | ||||||
|     CONSTEXPR11_TN static_string(const char* p, std::size_t N) NOEXCEPT_TN |   CONSTEXPR11_TN static_string(const char *p, std::size_t N) NOEXCEPT_TN | ||||||
|         : p_(p) |       : p_(p), | ||||||
|         , sz_(N) |         sz_(N) {} | ||||||
|         {} |  | ||||||
| 
 | 
 | ||||||
|     CONSTEXPR11_TN const char* data() const NOEXCEPT_TN {return p_;} |   CONSTEXPR11_TN const char *data() const NOEXCEPT_TN { return p_; } | ||||||
|     CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN {return sz_;} |   CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN { return sz_; } | ||||||
| 
 | 
 | ||||||
|     CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN {return p_;} |   CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN { return p_; } | ||||||
|     CONSTEXPR11_TN const_iterator end()   const NOEXCEPT_TN {return p_ + sz_;} |   CONSTEXPR11_TN const_iterator end() const NOEXCEPT_TN { return p_ + sz_; } | ||||||
| 
 | 
 | ||||||
|     CONSTEXPR11_TN char operator[](std::size_t n) const |   CONSTEXPR11_TN char operator[](std::size_t n) const { | ||||||
|     { |     return n < sz_ ? p_[n] : throw std::out_of_range("static_string"); | ||||||
|         return n < sz_ ? p_[n] : throw std::out_of_range("static_string"); |   } | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| inline | inline std::ostream &operator<<(std::ostream &os, static_string const &s) { | ||||||
| std::ostream& |   return os.write(s.data(), s.size()); | ||||||
| operator<<(std::ostream& os, static_string const& s) |  | ||||||
| { |  | ||||||
|     return os.write(s.data(), s.size()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <class T> | template <class T> CONSTEXPR14_TN static_string type_name() { | ||||||
| CONSTEXPR14_TN |   const int k = sizeof("constexpr soi::detail:: T") / sizeof(char); | ||||||
| static_string |  | ||||||
| type_name() |  | ||||||
| { |  | ||||||
|   const int k = sizeof("constexpr soi::detail:: T")/sizeof(char); |  | ||||||
| #ifdef __clang__ | #ifdef __clang__ | ||||||
|     static_string p = __PRETTY_FUNCTION__; |   static_string p = __PRETTY_FUNCTION__; | ||||||
|     return static_string(p.data() + 31 + k, p.size() - 31 - k - 1); |   return static_string(p.data() + 31 + k, p.size() - 31 - k - 1); | ||||||
| #elif defined(__GNUC__) | #elif defined(__GNUC__) | ||||||
|     static_string p = __PRETTY_FUNCTION__; |   static_string p = __PRETTY_FUNCTION__; | ||||||
| #  if __cplusplus < 201402 | #if __cplusplus < 201402 | ||||||
|     return static_string(p.data() + 36 + k, p.size() - 36 - k - 1); |   return static_string(p.data() + 36 + k, p.size() - 36 - k - 1); | ||||||
| #  else | #else | ||||||
|     return static_string(p.data() + 46 + k, p.size() - 46 - k - 1); |   return static_string(p.data() + 46 + k, p.size() - 46 - k - 1); | ||||||
| #  endif | #endif | ||||||
| #elif defined(_MSC_VER) | #elif defined(_MSC_VER) | ||||||
|     static_string p = __FUNCSIG__; |   static_string p = __FUNCSIG__; | ||||||
|     return static_string(p.data() + 38 + k, p.size() - 38 - k - 7); |   return static_string(p.data() + 38 + k, p.size() - 38 - k - 7); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| constexpr bool is_prefix_of(char const *suffix, char const *s) { | constexpr bool is_prefix_of(char const *suffix, char const *s) { | ||||||
|   return suffix[0]=='\0' || (suffix[0] == s[0] && is_prefix_of(suffix + 1, s + 1)); |   return suffix[0] == '\0' || | ||||||
|  |          (suffix[0] == s[0] && is_prefix_of(suffix + 1, s + 1)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static char const* const type_string = "string"; | static char const *const type_string = "string"; | ||||||
| 
 | 
 | ||||||
| template <class T> | template <class T> CONSTEXPR14_TN static_string sanitized_type_name() { | ||||||
| CONSTEXPR14_TN |  | ||||||
| static_string |  | ||||||
| sanitized_type_name() { |  | ||||||
|   CONSTEXPR14_TN static_string t = type_name<T>(); |   CONSTEXPR14_TN static_string t = type_name<T>(); | ||||||
|   CONSTEXPR14_TN std::size_t offset = |   CONSTEXPR14_TN std::size_t offset = | ||||||
|     is_prefix_of("std::__debug::", t.data()) ? sizeof("std::__debug::")-1 : |       is_prefix_of("std::__debug::", t.data()) | ||||||
|     is_prefix_of("std::", t.data()) ? sizeof("std::")-1 : |           ? sizeof("std::__debug::") - 1 | ||||||
|     0; |           : is_prefix_of("std::", t.data()) ? sizeof("std::") - 1 : 0; | ||||||
|   return |   return is_prefix_of("std::__cxx11::basic_string<char>", t.data()) | ||||||
|     is_prefix_of("std::__cxx11::basic_string<char>", t.data()) ? |              ? static_string(type_string, sizeof(type_string) - 2) | ||||||
|     static_string(type_string, sizeof(type_string)-2) : |              : static_string(t.data() + offset, t.size() - offset); | ||||||
|     static_string(t.data()+offset, t.size()-offset); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ----------------------------------------------------------------------------
 | // ----------------------------------------------------------------------------
 | ||||||
|  | @ -152,7 +138,7 @@ bool tty_supports_colors() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int has_environment_color_overwrite() { | int has_environment_color_overwrite() { | ||||||
|   if (const char* color_enabled = std::getenv("SOI_COLOR")) { |   if (const char *color_enabled = std::getenv("SOI_COLOR")) { | ||||||
|     if (!std::strcmp(color_enabled, "1")) |     if (!std::strcmp(color_enabled, "1")) | ||||||
|       return 1; |       return 1; | ||||||
|     if (!std::strcmp(color_enabled, "0")) |     if (!std::strcmp(color_enabled, "0")) | ||||||
|  | @ -172,12 +158,12 @@ bool are_colors_enabled() { | ||||||
| // init and static variables
 | // init and static variables
 | ||||||
| 
 | 
 | ||||||
| static bool colors_enabled = false; | static bool colors_enabled = false; | ||||||
| static const char* ANSI_DEBUG = ""; | static const char *ANSI_DEBUG = ""; | ||||||
| static const char* ANSI_EXPRESSION = ""; | static const char *ANSI_EXPRESSION = ""; | ||||||
| static const char* ANSI_VALUE = ""; | static const char *ANSI_VALUE = ""; | ||||||
| static const char* ANSI_TYPE = ""; | static const char *ANSI_TYPE = ""; | ||||||
| static const char* ANSI_MESSAGE = ""; | static const char *ANSI_MESSAGE = ""; | ||||||
| static const char* ANSI_RESET = ""; | static const char *ANSI_RESET = ""; | ||||||
| 
 | 
 | ||||||
| void dbg_init(bool with_colors) { | void dbg_init(bool with_colors) { | ||||||
|   if (with_colors) { |   if (with_colors) { | ||||||
|  | @ -199,70 +185,51 @@ void dbg_init(bool with_colors) { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void dbg_init() { | void dbg_init() { dbg_init(are_colors_enabled()); } | ||||||
|   dbg_init(are_colors_enabled()); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| // ----------------------------------------------------------------------------
 | // ----------------------------------------------------------------------------
 | ||||||
| // printer
 | // printer
 | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| T&& dbg_print(T&& value, | T &&dbg_print(T &&value, static_string const &type, char const *file, int line, | ||||||
|               static_string const& type, |               char const *function_name, char const *expression) { | ||||||
|               char const* file, |   const T &ref = value; | ||||||
|               int line, |   std::stringstream | ||||||
|               char const* function_name, |       value_buffer; // avoid nesting of dbg macros within print functinos
 | ||||||
|               char const* expression) { |  | ||||||
|   const T& ref = value; |  | ||||||
|   std::stringstream value_buffer; // avoid nesting of dbg macros within print functinos
 |  | ||||||
|   soi::print(value_buffer, ref); |   soi::print(value_buffer, ref); | ||||||
| 
 | 
 | ||||||
|   std::cerr << ANSI_DEBUG |   std::cerr << ANSI_DEBUG << "[" << file << ":" << line << " (" << function_name | ||||||
|             << "[" << file << ":" << line |             << ")] " << ANSI_RESET << ANSI_EXPRESSION << expression | ||||||
|             << " (" << function_name << ")] " << ANSI_RESET |             << ANSI_RESET << " = " << ANSI_VALUE << value_buffer.rdbuf() | ||||||
|             << ANSI_EXPRESSION << expression << ANSI_RESET |             << ANSI_RESET << " (" << ANSI_TYPE << type << ANSI_RESET << ")" | ||||||
|             << " = " |  | ||||||
|             << ANSI_VALUE << value_buffer.rdbuf() << ANSI_RESET |  | ||||||
|             << " (" << ANSI_TYPE << type << ANSI_RESET << ")" |  | ||||||
|             << '\n'; |             << '\n'; | ||||||
| 
 | 
 | ||||||
|   return std::forward<T>(value); |   return std::forward<T>(value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template<unsigned int N> | template <unsigned int N> | ||||||
| auto dbg_print(const char (&msg)[N], | auto dbg_print(const char (&msg)[N], static_string const &, char const *file, | ||||||
|                static_string const&, |                int line, char const *function_name, char const *expression) | ||||||
|                char const* file, |     -> decltype(msg) { | ||||||
|                int line, |   std::cerr << ANSI_DEBUG << "[" << file << ":" << line << " (" << function_name | ||||||
|                char const* function_name, |             << ")] " << ANSI_RESET << ANSI_MESSAGE << msg << ANSI_RESET << '\n'; | ||||||
|                char const* expression) -> decltype(msg) { |  | ||||||
|   std::cerr << ANSI_DEBUG |  | ||||||
|             << "[" << file << ":" << line |  | ||||||
|             << " (" << function_name << ")] " << ANSI_RESET |  | ||||||
|             << ANSI_MESSAGE << msg << ANSI_RESET |  | ||||||
|             << '\n'; |  | ||||||
|   return msg; |   return msg; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> T &&identity(T &&t) { return std::forward<T>(t); } | ||||||
| T&& identity(T&& t) { |  | ||||||
|   return std::forward<T>(t); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| } // end namespace detail
 | } // end namespace detail
 | ||||||
| 
 | 
 | ||||||
| } // end namespace dbg_macro
 | } // namespace soi
 | ||||||
| 
 | 
 | ||||||
| #ifdef SOI_RELEASE | #ifdef SOI_RELEASE | ||||||
| #define dbg(...) dbg_macro::identity(__VA_ARGS__) | #define dbg(...) dbg_macro::identity(__VA_ARGS__) | ||||||
| #else | #else | ||||||
| #define dbg(...)                                                        \ | #define dbg(...)                                                               \ | ||||||
|   soi::detail::dbg_print((__VA_ARGS__),                               \ |   soi::detail::dbg_print(                                                      \ | ||||||
|                            soi::detail::sanitized_type_name<decltype(__VA_ARGS__)>(), \ |       (__VA_ARGS__),                                                           \ | ||||||
|                            __FILE__,                                    \ |       soi::detail::sanitized_type_name<decltype(__VA_ARGS__)>(), __FILE__,     \ | ||||||
|                            __LINE__,                                    \ |       __LINE__, __func__, #__VA_ARGS__) | ||||||
|                            __func__,                                    \ |  | ||||||
|                            #__VA_ARGS__) |  | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #endif  // SOI_DBG
 | #endif // SOI_DBG
 | ||||||
|  |  | ||||||
|  | @ -1,24 +1,32 @@ | ||||||
| #pragma GCC diagnostic error "-Wdeprecated-declarations" | #pragma GCC diagnostic error "-Wdeprecated-declarations" | ||||||
| 
 | 
 | ||||||
| struct endl_is_evil_t {} endl_is_evil; | struct endl_is_evil_t { | ||||||
| [[deprecated("endl is evil.  Use '\\n' to print a newline.")]] std::ostream & operator<<(std::ostream &os, endl_is_evil_t); | } endl_is_evil; | ||||||
|  | [[deprecated("endl is evil.  Use '\\n' to print a newline.")]] std::ostream & | ||||||
|  | operator<<(std::ostream &os, endl_is_evil_t); | ||||||
| #define endl endl_is_evil | #define endl endl_is_evil | ||||||
| 
 | 
 | ||||||
| #define printf printf_is_evil | #define printf printf_is_evil | ||||||
| #define fprintf fprintf_is_evil | #define fprintf fprintf_is_evil | ||||||
| #define sprintf sprintf_is_evil | #define sprintf sprintf_is_evil | ||||||
| #define snprintf snprintf_is_evil | #define snprintf snprintf_is_evil | ||||||
| [[deprecated("printf is evil.  Use cout.")]] int printf(const char *format, ...); | [[deprecated("printf is evil.  Use cout.")]] int printf(const char *format, | ||||||
| [[deprecated("printf is evil.  Use cout.")]] int fprintf(std::FILE *stream, const char *format, ...); |                                                         ...); | ||||||
| [[deprecated("printf is evil.  Use cout.")]] int sprintf(char *buffer, const char *format, ...); | [[deprecated("printf is evil.  Use cout.")]] int | ||||||
| [[deprecated("printf is evil.  Use cout.")]] int snprintf(char *buffer, std::size_t buf_size, const char *format, ...); | fprintf(std::FILE *stream, const char *format, ...); | ||||||
|  | [[deprecated("printf is evil.  Use cout.")]] int | ||||||
|  | sprintf(char *buffer, const char *format, ...); | ||||||
|  | [[deprecated("printf is evil.  Use cout.")]] int | ||||||
|  | snprintf(char *buffer, std::size_t buf_size, const char *format, ...); | ||||||
| 
 | 
 | ||||||
| #define scanf scanf_is_evil | #define scanf scanf_is_evil | ||||||
| #define fscanf fscanf_is_evil | #define fscanf fscanf_is_evil | ||||||
| #define sscanf sscanf_is_evil | #define sscanf sscanf_is_evil | ||||||
| [[deprecated("scanf is evil.  Use cin.")]] int scanf(const char *format, ...); | [[deprecated("scanf is evil.  Use cin.")]] int scanf(const char *format, ...); | ||||||
| [[deprecated("scanf is evil.  Use cin.")]] int fscanf(std::FILE *stream, const char *format, ...); | [[deprecated("scanf is evil.  Use cin.")]] int fscanf(std::FILE *stream, | ||||||
| [[deprecated("scanf is evil.  Use cin.")]] int sscanf(const char *buffer, const char *format, ...); |                                                       const char *format, ...); | ||||||
|  | [[deprecated("scanf is evil.  Use cin.")]] int sscanf(const char *buffer, | ||||||
|  |                                                       const char *format, ...); | ||||||
| 
 | 
 | ||||||
| #define puts puts_is_evil | #define puts puts_is_evil | ||||||
| #define fputs fputs_is_evil | #define fputs fputs_is_evil | ||||||
|  | @ -35,28 +43,45 @@ struct endl_is_evil_t {} endl_is_evil; | ||||||
| #define fread fread_is_evil | #define fread fread_is_evil | ||||||
| #define fwrite fwrite_is_evil | #define fwrite fwrite_is_evil | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int puts(const char *str); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int puts(const char *str); | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int fputs(const char *str, FILE *stream); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int fputs(const char *str, | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] char *fgets(char *str, int count, FILE *stream); |                                                              FILE *stream); | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] std::FILE *freopen(const char *filename, const char *mode, std::FILE *stream); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] char * | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] std::FILE *fopen(const char *filename, const char *mode); | fgets(char *str, int count, FILE *stream); | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int fclose(std::FILE *stream); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] std::FILE * | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int fflush(std::FILE *stream); | freopen(const char *filename, const char *mode, std::FILE *stream); | ||||||
|  | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] std::FILE * | ||||||
|  | fopen(const char *filename, const char *mode); | ||||||
|  | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int | ||||||
|  | fclose(std::FILE *stream); | ||||||
|  | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int | ||||||
|  | fflush(std::FILE *stream); | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int getchar(); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int getchar(); | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int fgetc(std::FILE *stream); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int fgetc(std::FILE *stream); | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int getc(std::FILE *stream); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int getc(std::FILE *stream); | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] void setbuf(std::FILE *stream, char *buffer); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] void | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int setvbuf(std::FILE *stream, char *buffer, int mode, std::size_t size); | setbuf(std::FILE *stream, char *buffer); | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] std::size_t fread(void *buffer, std::size_t size, std::size_t count, std::FILE *stream); | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] int | ||||||
| [[deprecated("<cstdio> is evil.  Use cin/cout.")]] std::size_t fwrite(const void *buffer, std::size_t size, std::size_t count, std::FILE *stream); | setvbuf(std::FILE *stream, char *buffer, int mode, std::size_t size); | ||||||
|  | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] std::size_t | ||||||
|  | fread(void *buffer, std::size_t size, std::size_t count, std::FILE *stream); | ||||||
|  | [[deprecated("<cstdio> is evil.  Use cin/cout.")]] std::size_t | ||||||
|  | fwrite(const void *buffer, std::size_t size, std::size_t count, | ||||||
|  |        std::FILE *stream); | ||||||
| 
 | 
 | ||||||
| #define malloc malloc_is_evil | #define malloc malloc_is_evil | ||||||
| #define calloc calloc_is_evil | #define calloc calloc_is_evil | ||||||
| #define realloc realloc_is_evil | #define realloc realloc_is_evil | ||||||
| #define free free_is_evil | #define free free_is_evil | ||||||
| [[deprecated("malloc/free is evil.  Use a vector.")]] void *malloc(std::size_t size); | [[deprecated("malloc/free is evil.  Use a vector.")]] void * | ||||||
| [[deprecated("malloc/free is evil.  Use a vector.")]] void *calloc(std::size_t num, std::size_t size); | malloc(std::size_t size); | ||||||
| [[deprecated("malloc/free is evil.  Use a vector.")]] void *realloc(void *ptr, std::size_t new_size); | [[deprecated("malloc/free is evil.  Use a vector.")]] void * | ||||||
| [[deprecated("malloc/free is evil.  Use a vector.")]] void *free(void *ptr, std::size_t new_size); | calloc(std::size_t num, std::size_t size); | ||||||
|  | [[deprecated("malloc/free is evil.  Use a vector.")]] void * | ||||||
|  | realloc(void *ptr, std::size_t new_size); | ||||||
|  | [[deprecated("malloc/free is evil.  Use a vector.")]] void * | ||||||
|  | free(void *ptr, std::size_t new_size); | ||||||
| 
 | 
 | ||||||
| [[deprecated("new is evil.  Use a vector.")]] void *operator new(std::size_t sz); | [[deprecated("new is evil.  Use a vector.")]] void * | ||||||
| [[deprecated("delete is evil.  Use a vector.")]] void operator delete(void *ptr) noexcept; | operator new(std::size_t sz); | ||||||
|  | [[deprecated("delete is evil.  Use a vector.")]] void | ||||||
|  | operator delete(void *ptr) noexcept; | ||||||
|  |  | ||||||
|  | @ -13,63 +13,88 @@ | ||||||
| 
 | 
 | ||||||
| namespace soi { | namespace soi { | ||||||
| 
 | 
 | ||||||
| template<typename TChar, typename TCharTraits> | template <typename TChar, typename TCharTraits> | ||||||
| std::basic_ostream<TChar, TCharTraits> & | std::basic_ostream<TChar, TCharTraits> & | ||||||
| pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const bool& x) { | pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, const bool &x) { | ||||||
|   return stream << (x ? "true" : "false"); |   return stream << (x ? "true" : "false"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace detail { | namespace detail { | ||||||
| template<typename TChar, typename TCharTraits> | template <typename TChar, typename TCharTraits> | ||||||
| void escape_char(std::basic_ostream<TChar, TCharTraits> & stream, char c) { | void escape_char(std::basic_ostream<TChar, TCharTraits> &stream, char c) { | ||||||
|   switch (c) { |   switch (c) { | ||||||
|   case '\a': stream << "\\a"; break; |   case '\a': | ||||||
|   case '\b': stream << "\\b"; break; |     stream << "\\a"; | ||||||
|   case '\t': stream << "\\t"; break; |     break; | ||||||
|   case '\n': stream << "\\n"; break; |   case '\b': | ||||||
|   case '\v': stream << "\\v"; break; |     stream << "\\b"; | ||||||
|   case '\f': stream << "\\f"; break; |     break; | ||||||
|   case '\r': stream << "\\r"; break; |   case '\t': | ||||||
|   case '\e': stream << "\\e"; break; |     stream << "\\t"; | ||||||
|   case '\"': stream << "\\\""; break; |     break; | ||||||
|   case '\'': stream << "\\'"; break; |   case '\n': | ||||||
|   case '\?': stream << "\\?"; break; |     stream << "\\n"; | ||||||
|   case '\\': stream << "\\\\"; break; |     break; | ||||||
|   default: stream << c; |   case '\v': | ||||||
|  |     stream << "\\v"; | ||||||
|  |     break; | ||||||
|  |   case '\f': | ||||||
|  |     stream << "\\f"; | ||||||
|  |     break; | ||||||
|  |   case '\r': | ||||||
|  |     stream << "\\r"; | ||||||
|  |     break; | ||||||
|  |   case '\e': | ||||||
|  |     stream << "\\e"; | ||||||
|  |     break; | ||||||
|  |   case '\"': | ||||||
|  |     stream << "\\\""; | ||||||
|  |     break; | ||||||
|  |   case '\'': | ||||||
|  |     stream << "\\'"; | ||||||
|  |     break; | ||||||
|  |   case '\?': | ||||||
|  |     stream << "\\?"; | ||||||
|  |     break; | ||||||
|  |   case '\\': | ||||||
|  |     stream << "\\\\"; | ||||||
|  |     break; | ||||||
|  |   default: | ||||||
|  |     stream << c; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| } | } // namespace detail
 | ||||||
| 
 | 
 | ||||||
| template<typename TChar, typename TCharTraits> | template <typename TChar, typename TCharTraits> | ||||||
| std::basic_ostream<TChar, TCharTraits> & | std::basic_ostream<TChar, TCharTraits> & | ||||||
| pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const std::string& x) { | pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, | ||||||
|  |              const std::string &x) { | ||||||
|   stream << "\""; |   stream << "\""; | ||||||
|   for (char c : x) |   for (char c : x) | ||||||
|     detail::escape_char(stream, c); |     detail::escape_char(stream, c); | ||||||
|   return stream << "\""; |   return stream << "\""; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template<typename TChar, typename TCharTraits> | template <typename TChar, typename TCharTraits> | ||||||
| std::basic_ostream<TChar, TCharTraits> & | std::basic_ostream<TChar, TCharTraits> & | ||||||
| pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, char c) { | pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, char c) { | ||||||
|   stream << "'"; |   stream << "'"; | ||||||
|   detail::escape_char(stream, c); |   detail::escape_char(stream, c); | ||||||
|   return stream << "'"; |   return stream << "'"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template<typename T, typename TChar, typename TCharTraits> | template <typename T, typename TChar, typename TCharTraits> | ||||||
| inline typename std::enable_if< !::soi::is_container<T>::value, | inline typename std::enable_if<!::soi::is_container<T>::value, | ||||||
|                                 std::basic_ostream<TChar, TCharTraits> &>::type |                                std::basic_ostream<TChar, TCharTraits> &>::type | ||||||
| pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const T& x) { | pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, const T &x) { | ||||||
|   return stream << x; |   return stream << x; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | template <typename T, typename TChar, typename TCharTraits> | ||||||
| template<typename T, typename TChar, typename TCharTraits> |  | ||||||
| std::basic_ostream<TChar, TCharTraits> & | std::basic_ostream<TChar, TCharTraits> & | ||||||
| print(std::basic_ostream<TChar, TCharTraits> & stream, const T& x) { | print(std::basic_ostream<TChar, TCharTraits> &stream, const T &x) { | ||||||
|   return pretty_print(stream, x); |   return pretty_print(stream, x); | ||||||
| } | } | ||||||
| } | } // namespace soi
 | ||||||
| 
 | 
 | ||||||
| #endif // SOI_PRETTY
 | #endif // SOI_PRETTY
 | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								include/soi
								
								
								
								
							
							
						
						
									
										18
									
								
								include/soi
								
								
								
								
							|  | @ -5,20 +5,20 @@ | ||||||
|    have to understand every concept all at once. |    have to understand every concept all at once. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| #include <fstream> |  | ||||||
| #include "bits/soi-dbg.hpp" | #include "bits/soi-dbg.hpp" | ||||||
|  | #include <fstream> | ||||||
| 
 | 
 | ||||||
| namespace soi { | namespace soi { | ||||||
| 
 | 
 | ||||||
| void check_for_eof() { | void check_for_eof() { | ||||||
|     if (!(std::cin >> std::ws).eof()) |   if (!(std::cin >> std::ws).eof()) | ||||||
|         std::cerr << "WARNING: didn't read the whole input\n"; |     std::cerr << "WARNING: didn't read the whole input\n"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void noninteractive_check_eof() { | void noninteractive_check_eof() { | ||||||
|   // make symbol 0x1A (Ctrl+Z) a whitespace |   // make symbol 0x1A (Ctrl+Z) a whitespace | ||||||
|   struct console_ctype : std::ctype<char> { |   struct console_ctype : std::ctype<char> { | ||||||
|     static const mask* get_table() { |     static const mask *get_table() { | ||||||
|       static const std::array<mask, table_size> table = []() { |       static const std::array<mask, table_size> table = []() { | ||||||
|         std::array<mask, table_size> table; |         std::array<mask, table_size> table; | ||||||
|         std::copy(classic_table(), classic_table() + table_size, table.begin()); |         std::copy(classic_table(), classic_table() + table_size, table.begin()); | ||||||
|  | @ -27,14 +27,14 @@ void noninteractive_check_eof() { | ||||||
|       }(); |       }(); | ||||||
|       return table.data(); |       return table.data(); | ||||||
|     } |     } | ||||||
|   console_ctype(std::size_t refs = 0) : ctype(get_table(), false, refs) {} |     console_ctype(std::size_t refs = 0) : ctype(get_table(), false, refs) {} | ||||||
|   }; |   }; | ||||||
|   std::cin.imbue(std::locale(std::cin.getloc(), new console_ctype)); |   std::cin.imbue(std::locale(std::cin.getloc(), new console_ctype)); | ||||||
|   check_for_eof(); |   check_for_eof(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool should_check_for_eof() { | bool should_check_for_eof() { | ||||||
|   if (const char* eofcheck_enabled = std::getenv("SOI_EOFCHECK")) { |   if (const char *eofcheck_enabled = std::getenv("SOI_EOFCHECK")) { | ||||||
|     if (!std::strcmp(eofcheck_enabled, "1")) |     if (!std::strcmp(eofcheck_enabled, "1")) | ||||||
|       return true; |       return true; | ||||||
|     if (!std::strcmp(eofcheck_enabled, "0")) |     if (!std::strcmp(eofcheck_enabled, "0")) | ||||||
|  | @ -48,9 +48,9 @@ void initialize_debug() { | ||||||
|   std::cin.exceptions(std::ifstream::failbit | std::ifstream::badbit); |   std::cin.exceptions(std::ifstream::failbit | std::ifstream::badbit); | ||||||
|   std::ios::sync_with_stdio(false); |   std::ios::sync_with_stdio(false); | ||||||
| 
 | 
 | ||||||
|   if (should_check_for_eof() && |   if (should_check_for_eof() && std::atexit(noninteractive_check_eof) != 0) { | ||||||
|       std::atexit(noninteractive_check_eof) != 0) { |     std::cerr | ||||||
|     std::cerr << "WARNING: soi.h -- registration of sanity check at exit failed\n"; |         << "WARNING: soi.h -- registration of sanity check at exit failed\n"; | ||||||
|   } |   } | ||||||
|   soi::detail::dbg_init(); |   soi::detail::dbg_init(); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue