From 310d119ffbc6da18e1bac8957ad9d96c54f3db27 Mon Sep 17 00:00:00 2001 From: Johannes Kapfhammer Date: Sun, 6 Oct 2019 18:35:55 +0200 Subject: [PATCH 1/3] include map --- include/bits/include-all.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/bits/include-all.hpp b/include/bits/include-all.hpp index 639d3df..b75e18e 100644 --- a/include/bits/include-all.hpp +++ b/include/bits/include-all.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include From 4d25fc25c4fc769784e161f05614f1783ef78724 Mon Sep 17 00:00:00 2001 From: Johannes Kapfhammer Date: Sun, 6 Oct 2019 18:37:37 +0200 Subject: [PATCH 2/3] fix pretty printer for recursive types --- example.cpp | 7 +- include/bits/prettyprint.hpp | 734 ++++++++++++++++++----------------- include/bits/soi-dbg.hpp | 10 +- include/bits/soi-pretty.hpp | 19 +- include/soi | 14 +- 5 files changed, 396 insertions(+), 388 deletions(-) diff --git a/example.cpp b/example.cpp index 0568cef..9281c42 100644 --- a/example.cpp +++ b/example.cpp @@ -1,7 +1,7 @@ // compile-command: "g++ -Iinclude -D_GLIBCXX_DEBUG -fsanitize=address,undefined -g3 -ggdb3 -std=c++17 example.cpp -o example && SOI_H_COLOR=1 SOI_H_EOFCHECK=1 ./example <<< ''" #include -signed main() { +signed main() { dbg("hi"); string s="world"; dbg(s); @@ -11,6 +11,9 @@ signed main() { vector pi{3,1,4,1,5,9,2,6}; dbg(pi); dbg(vector{3,1,4,1,5,9,2,6}); - dbg(pi); + dbg(vector>{{3,1},{4,1}}); + dbg(vector>>{{3,{"hi"}},{4,{"hello", "world"}}}); + dbg(set{3,1,4}); + dbg(map{{3,"three"},{1,"one"}}); cout << "hi\n"; } diff --git a/include/bits/prettyprint.hpp b/include/bits/prettyprint.hpp index a480c97..52d720b 100644 --- a/include/bits/prettyprint.hpp +++ b/include/bits/prettyprint.hpp @@ -21,424 +21,430 @@ #include #include -namespace pretty_print +namespace soi { + +template +std::basic_ostream & +print(std::basic_ostream & stream, const T& x); + +namespace detail { - namespace detail +// SFINAE type trait to detect whether T::const_iterator exists. + +struct sfinae_base +{ + using yes = char; + using no = yes[2]; +}; + +template +struct has_const_iterator : private sfinae_base +{ +private: + template static yes & test(typename C::const_iterator*); + template static no & test(...); +public: + static const bool value = sizeof(test(nullptr)) == sizeof(yes); + using type = T; +}; + +template +struct has_begin_end : private sfinae_base +{ +private: + template + static yes & f(typename std::enable_if< + std::is_same(&C::begin)), + typename C::const_iterator(C::*)() const>::value>::type *); + + template static no & f(...); + + template + static yes & g(typename std::enable_if< + std::is_same(&C::end)), + typename C::const_iterator(C::*)() const>::value, void>::type*); + + template static no & g(...); + +public: + static bool const beg_value = sizeof(f(nullptr)) == sizeof(yes); + static bool const end_value = sizeof(g(nullptr)) == sizeof(yes); +}; + +} // namespace detail + + +// Holds the delimiter values for a specific character type + +template +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 +struct delimiters +{ + using type = delimiters_values; + static const type values; +}; + + +// 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 +// be customized by specializing the nested template. + +template , + typename TDelimiters = delimiters> +struct pretty_print_container_helper +{ + using delimiters_type = TDelimiters; + using ostream_type = std::basic_ostream; + + template + struct pretty_printer { - // SFINAE type trait to detect whether T::const_iterator exists. - - struct sfinae_base + static void pretty_print_body(const U & c, ostream_type & stream) { - using yes = char; - using no = yes[2]; - }; + using std::begin; + using std::end; - template - struct has_const_iterator : private sfinae_base - { - private: - template static yes & test(typename C::const_iterator*); - template static no & test(...); - public: - static const bool value = sizeof(test(nullptr)) == sizeof(yes); - using type = T; - }; + auto it = begin(c); + const auto the_end = end(c); - template - struct has_begin_end : private sfinae_base - { - private: - template - static yes & f(typename std::enable_if< - std::is_same(&C::begin)), - typename C::const_iterator(C::*)() const>::value>::type *); - - template static no & f(...); - - template - static yes & g(typename std::enable_if< - std::is_same(&C::end)), - typename C::const_iterator(C::*)() const>::value, void>::type*); - - template static no & g(...); - - public: - static bool const beg_value = sizeof(f(nullptr)) == sizeof(yes); - static bool const end_value = sizeof(g(nullptr)) == sizeof(yes); - }; - - } // namespace detail - - - // Holds the delimiter values for a specific character type - - template - 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 - struct delimiters - { - using type = delimiters_values; - 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 TDelimiters = delimiters> - struct print_container_helper - { - using delimiters_type = TDelimiters; - using ostream_type = std::basic_ostream; - - template - 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) + if (it != the_end) { for ( ; ; ) - { - stream << *it; + { + ::soi::print(stream, *it); - if (++it == the_end) break; + if (++it == the_end) break; - if (delimiters_type::values.delimiter != NULL) - stream << delimiters_type::values.delimiter; - } + if (delimiters_type::values.delimiter != NULL) + ::soi::print(stream, delimiters_type::values.delimiter); + } } - } - }; + } + }; - print_container_helper(const T & container) + pretty_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::print_body(container_, stream); - - if (delimiters_type::values.postfix != NULL) - stream << delimiters_type::values.postfix; - } - - private: - const T & container_; - }; - - // Specialization for pairs - - template - template - struct print_container_helper::printer> + inline void operator()(ostream_type & stream) const { - using ostream_type = typename print_container_helper::ostream_type; + if (delimiters_type::values.prefix != NULL) + ::soi::print(stream, delimiters_type::values.prefix); - static void print_body(const std::pair & c, ostream_type & stream) - { - stream << c.first; - if (print_container_helper::delimiters_type::values.delimiter != NULL) - stream << print_container_helper::delimiters_type::values.delimiter; - stream << c.second; - } - }; + pretty_printer::pretty_print_body(container_, stream); - // Specialization for tuples - - template - template - struct print_container_helper::printer> - { - using ostream_type = typename print_container_helper::ostream_type; - using element_type = std::tuple; - - template 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) - { - } - - static void tuple_print(const element_type & c, ostream_type & stream, - typename std::conditional, std::nullptr_t>::type) - { - stream << std::get<0>(c); - tuple_print(c, stream, Int<1>()); - } - - template - static void tuple_print(const element_type & c, ostream_type & stream, Int) - { - if (print_container_helper::delimiters_type::values.delimiter != NULL) - stream << print_container_helper::delimiters_type::values.delimiter; - - stream << std::get(c); - - tuple_print(c, stream, Int()); - } - }; - - // Prints a print_container_helper to the specified stream. - - template - inline std::basic_ostream & operator<<( - std::basic_ostream & stream, - const print_container_helper & helper) - { - helper(stream); - return stream; + if (delimiters_type::values.postfix != NULL) + ::soi::print(stream, delimiters_type::values.postfix); } +private: + const T & container_; +}; - // Basic is_container template; specialize to derive from std::true_type for all desired container types +// Specialization for pairs - template - struct is_container : public std::integral_constant::value && - detail::has_begin_end::beg_value && - detail::has_begin_end::end_value> { }; +template +template +struct pretty_print_container_helper::pretty_printer> +{ + using ostream_type = typename pretty_print_container_helper::ostream_type; - template - struct is_container : std::true_type { }; + static void pretty_print_body(const std::pair & c, ostream_type & stream) + { + ::soi::print(stream, c.first); + if (pretty_print_container_helper::delimiters_type::values.delimiter != NULL) + ::soi::print(stream, pretty_print_container_helper::delimiters_type::values.delimiter); + ::soi::print(stream, c.second); + } +}; + +// Specialization for tuples + +template +template +struct pretty_print_container_helper::pretty_printer> +{ + using ostream_type = typename pretty_print_container_helper::ostream_type; + using element_type = std::tuple; + + template struct Int { }; + + static void pretty_print_body(const element_type & c, ostream_type & stream) + { + tuple_pretty_print(c, stream, Int<0>()); + } + + static void tuple_pretty_print(const element_type &, ostream_type &, Int) + { + } + + static void tuple_pretty_print(const element_type & c, ostream_type & stream, + typename std::conditional, std::nullptr_t>::type) + { + ::soi::print(stream, std::get<0>(c)); + tuple_pretty_print(c, stream, Int<1>()); + } template - struct is_container : std::false_type { }; - - template - struct is_container> : std::true_type { }; - - template - struct is_container> : std::true_type { }; - - template - struct is_container> : std::true_type { }; - - - // Default delimiters - - template struct delimiters { static const delimiters_values values; }; - template const delimiters_values delimiters::values = { "[", ", ", "]" }; - template struct delimiters { static const delimiters_values values; }; - template const delimiters_values delimiters::values = { L"[", L", ", L"]" }; - - - // Delimiters for (multi)set and unordered_(multi)set - - template - struct delimiters< ::std::set, char> { static const delimiters_values values; }; - - template - const delimiters_values delimiters< ::std::set, char>::values = { "{", ", ", "}" }; - - template - struct delimiters< ::std::set, wchar_t> { static const delimiters_values values; }; - - template - const delimiters_values delimiters< ::std::set, wchar_t>::values = { L"{", L", ", L"}" }; - - template - struct delimiters< ::std::multiset, char> { static const delimiters_values values; }; - - template - const delimiters_values delimiters< ::std::multiset, char>::values = { "{", ", ", "}" }; - - template - struct delimiters< ::std::multiset, wchar_t> { static const delimiters_values values; }; - - template - const delimiters_values delimiters< ::std::multiset, wchar_t>::values = { L"{", L", ", L"}" }; - - template - struct delimiters< ::std::unordered_set, char> { static const delimiters_values values; }; - - template - const delimiters_values delimiters< ::std::unordered_set, char>::values = { "{", ", ", "}" }; - - template - struct delimiters< ::std::unordered_set, wchar_t> { static const delimiters_values values; }; - - template - const delimiters_values delimiters< ::std::unordered_set, wchar_t>::values = { L"{", L", ", L"}" }; - - template - struct delimiters< ::std::unordered_multiset, char> { static const delimiters_values values; }; - - template - const delimiters_values delimiters< ::std::unordered_multiset, char>::values = { "{", ", ", "}" }; - - template - struct delimiters< ::std::unordered_multiset, wchar_t> { static const delimiters_values values; }; - - template - const delimiters_values delimiters< ::std::unordered_multiset, wchar_t>::values = { L"{", L", ", L"}" }; - - - // Delimiters for pair and tuple - - template struct delimiters, char> { static const delimiters_values values; }; - template const delimiters_values delimiters, char>::values = { "(", ", ", ")" }; - template struct delimiters< ::std::pair, wchar_t> { static const delimiters_values values; }; - template const delimiters_values delimiters< ::std::pair, wchar_t>::values = { L"(", L", ", L")" }; - - template struct delimiters, char> { static const delimiters_values values; }; - template const delimiters_values delimiters, char>::values = { "(", ", ", ")" }; - template struct delimiters< ::std::tuple, wchar_t> { static const delimiters_values values; }; - template const delimiters_values delimiters< ::std::tuple, wchar_t>::values = { L"(", L", ", L")" }; - - - // Type-erasing helper class for easy use of custom delimiters. - // Requires TCharTraits = std::char_traits and TChar = char or wchar_t, and MyDelims needs to be defined for TChar. - // Usage: "cout << pretty_print::custom_delims(x)". - - struct custom_delims_base + static void tuple_pretty_print(const element_type & c, ostream_type & stream, Int) { - virtual ~custom_delims_base() { } - virtual std::ostream & stream(::std::ostream &) = 0; - virtual std::wostream & stream(::std::wostream &) = 0; - }; + if (pretty_print_container_helper::delimiters_type::values.delimiter != NULL) + ::soi::print(stream, pretty_print_container_helper::delimiters_type::values.delimiter); - template - struct custom_delims_wrapper : custom_delims_base + ::soi::print(stream, std::get(c)); + + tuple_pretty_print(c, stream, Int()); + } +}; + +// Pretty_Prints a pretty_print_container_helper to the specified stream. + +template +inline std::basic_ostream & pretty_print( + std::basic_ostream & stream, + const pretty_print_container_helper & helper) +{ + helper(stream); + return stream; +} + + +// Basic is_container template; specialize to derive from std::true_type for all desired container types + +template +struct is_container : public std::integral_constant::value && + detail::has_begin_end::beg_value && + detail::has_begin_end::end_value> { }; + +template +struct is_container : std::true_type { }; + +template +struct is_container : std::false_type { }; + +template +struct is_container> : std::true_type { }; + +template +struct is_container> : std::true_type { }; + +template +struct is_container> : std::true_type { }; + + +// Default delimiters + +template struct delimiters { static const delimiters_values values; }; +template const delimiters_values delimiters::values = { "[", ", ", "]" }; +template struct delimiters { static const delimiters_values values; }; +template const delimiters_values delimiters::values = { L"[", L", ", L"]" }; + + +// Delimiters for (multi)set and unordered_(multi)set + +template +struct delimiters< ::std::set, char> { static const delimiters_values values; }; + +template +const delimiters_values delimiters< ::std::set, char>::values = { "{", ", ", "}" }; + +template +struct delimiters< ::std::set, wchar_t> { static const delimiters_values values; }; + +template +const delimiters_values delimiters< ::std::set, wchar_t>::values = { L"{", L", ", L"}" }; + +template +struct delimiters< ::std::multiset, char> { static const delimiters_values values; }; + +template +const delimiters_values delimiters< ::std::multiset, char>::values = { "{", ", ", "}" }; + +template +struct delimiters< ::std::multiset, wchar_t> { static const delimiters_values values; }; + +template +const delimiters_values delimiters< ::std::multiset, wchar_t>::values = { L"{", L", ", L"}" }; + +template +struct delimiters< ::std::unordered_set, char> { static const delimiters_values values; }; + +template +const delimiters_values delimiters< ::std::unordered_set, char>::values = { "{", ", ", "}" }; + +template +struct delimiters< ::std::unordered_set, wchar_t> { static const delimiters_values values; }; + +template +const delimiters_values delimiters< ::std::unordered_set, wchar_t>::values = { L"{", L", ", L"}" }; + +template +struct delimiters< ::std::unordered_multiset, char> { static const delimiters_values values; }; + +template +const delimiters_values delimiters< ::std::unordered_multiset, char>::values = { "{", ", ", "}" }; + +template +struct delimiters< ::std::unordered_multiset, wchar_t> { static const delimiters_values values; }; + +template +const delimiters_values delimiters< ::std::unordered_multiset, wchar_t>::values = { L"{", L", ", L"}" }; + + +// Delimiters for pair and tuple + +template struct delimiters, char> { static const delimiters_values values; }; +template const delimiters_values delimiters, char>::values = { "(", ", ", ")" }; +template struct delimiters< ::std::pair, wchar_t> { static const delimiters_values values; }; +template const delimiters_values delimiters< ::std::pair, wchar_t>::values = { L"(", L", ", L")" }; + +template struct delimiters, char> { static const delimiters_values values; }; +template const delimiters_values delimiters, char>::values = { "(", ", ", ")" }; +template struct delimiters< ::std::tuple, wchar_t> { static const delimiters_values values; }; +template const delimiters_values delimiters< ::std::tuple, wchar_t>::values = { L"(", L", ", L")" }; + + +// Type-erasing helper class for easy use of custom delimiters. +// Requires TCharTraits = std::char_traits and TChar = char or wchar_t, and MyDelims needs to be defined for TChar. +// Usage: "cout << pretty_pretty_print::custom_delims(x)". + +struct custom_delims_base +{ + virtual ~custom_delims_base() { } + virtual std::ostream & stream(::std::ostream &) = 0; + virtual std::wostream & stream(::std::wostream &) = 0; +}; + +template +struct custom_delims_wrapper : custom_delims_base +{ + custom_delims_wrapper(const T & t_) : t(t_) { } + + std::ostream & stream(std::ostream & s) { - custom_delims_wrapper(const T & t_) : t(t_) { } - - std::ostream & stream(std::ostream & s) - { - return s << print_container_helper, Delims>(t); - } - - std::wostream & stream(std::wostream & s) - { - return s << print_container_helper, Delims>(t); - } - - private: - const T & t; - }; - - template - struct custom_delims - { - template - custom_delims(const Container & c) : base(new custom_delims_wrapper(c)) { } - - std::unique_ptr base; - }; - - template - inline std::basic_ostream & operator<<(std::basic_ostream & s, const custom_delims & p) - { - return p.base->stream(s); + return pretty_print(s, pretty_print_container_helper, Delims>(t)); } - - // A wrapper for a C-style array given as pointer-plus-size. - // Usage: std::cout << pretty_print_array(arr, n) << std::endl; - - template - struct array_wrapper_n + std::wostream & stream(std::wostream & s) { - typedef const T * const_iterator; - typedef T value_type; + return pretty_print(s, pretty_print_container_helper, Delims>(t)); + } - 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 & t; +}; - private: - const T * const _array; - size_t _n; - }; +template +struct custom_delims +{ + template + custom_delims(const Container & c) : base(new custom_delims_wrapper(c)) { } + + std::unique_ptr base; +}; + +template +inline std::basic_ostream & pretty_print(std::basic_ostream & s, const custom_delims & p) +{ + return p.base->stream(s); +} - // 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.) +// A wrapper for a C-style array given as pointer-plus-size. +// Usage: std::cout << pretty_pretty_print_array(arr, n) << std::endl; - template - struct bucket_print_wrapper +template +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_pretty_print(m, 4) << std::endl; (Pretty_Prints bucket 5 of container m.) + +template +struct bucket_pretty_print_wrapper +{ + typedef typename T::const_local_iterator const_iterator; + typedef typename T::size_type size_type; + + const_iterator begin() const { - typedef typename T::const_local_iterator const_iterator; - typedef typename T::size_type size_type; + return m_map.cbegin(n); + } - const_iterator begin() const - { - return m_map.cbegin(n); - } + const_iterator end() const + { + return m_map.cend(n); + } - const_iterator end() const - { - return m_map.cend(n); - } + bucket_pretty_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { } - bucket_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { } +private: + const T & m_map; + const size_type n; +}; - private: - const T & m_map; - const size_type n; - }; - -} // namespace pretty_print +} // namespace soi /* // Global accessor functions for the convenience wrappers template -inline pretty_print::array_wrapper_n pretty_print_array(const T * const a, size_t n) +inline pretty_pretty_print::array_wrapper_n pretty_pretty_print_array(const T * const a, size_t n) { - return pretty_print::array_wrapper_n(a, n); +return pretty_pretty_print::array_wrapper_n(a, n); } -template pretty_print::bucket_print_wrapper -bucket_print(const T & m, typename T::size_type n) +template pretty_pretty_print::bucket_pretty_print_wrapper +bucket_pretty_print(const T & m, typename T::size_type n) { - return pretty_print::bucket_print_wrapper(m, n); +return pretty_pretty_print::bucket_pretty_print_wrapper(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 - inline typename enable_if< ::pretty_print::is_container::value, - basic_ostream &>::type - operator<<(basic_ostream & stream, const T & container) - { - return stream << ::pretty_print::print_container_helper(container); - } -} */ -#endif // SOI_PRETTY_PRINT +namespace soi +{ +// Pretty_Prints a container to the stream using default delimiters + +template +inline typename std::enable_if< ::soi::is_container::value, + std::basic_ostream &>::type +pretty_print(std::basic_ostream & stream, const T & container) +{ + return ::soi::print(stream, ::soi::pretty_print_container_helper(container)); +} +} + + +#endif // SOI_PRETTY_PRETTY_PRINT diff --git a/include/bits/soi-dbg.hpp b/include/bits/soi-dbg.hpp index b45b678..d3544c7 100644 --- a/include/bits/soi-dbg.hpp +++ b/include/bits/soi-dbg.hpp @@ -23,7 +23,7 @@ #include "soi-pretty.hpp" -namespace soi_h { +namespace soi { namespace detail { @@ -102,7 +102,7 @@ CONSTEXPR14_TN static_string type_name() { - const int k = sizeof("constexpr soi_h::detail:: T =")/sizeof(char); + const int k = sizeof("constexpr soi::detail:: T")/sizeof(char); #ifdef __clang__ static_string p = __PRETTY_FUNCTION__; return static_string(p.data() + 31 + k, p.size() - 31 - k - 1); @@ -215,7 +215,7 @@ T&& dbg_print(T&& value, char const* expression) { const T& ref = value; std::stringstream value_buffer; // avoid nesting of dbg macros within print functinos - soi_h::pretty_print(value_buffer, ref); + soi::print(value_buffer, ref); std::cerr << ANSI_DEBUG << "[" << file << ":" << line @@ -257,8 +257,8 @@ T&& identity(T&& t) { #define dbg(...) dbg_macro::identity(__VA_ARGS__) #else #define dbg(...) \ - soi_h::detail::dbg_print((__VA_ARGS__), \ - soi_h::detail::sanitized_type_name(), \ + soi::detail::dbg_print((__VA_ARGS__), \ + soi::detail::sanitized_type_name(), \ __FILE__, \ __LINE__, \ __func__, \ diff --git a/include/bits/soi-pretty.hpp b/include/bits/soi-pretty.hpp index 116bdf5..13925a1 100644 --- a/include/bits/soi-pretty.hpp +++ b/include/bits/soi-pretty.hpp @@ -3,7 +3,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // -// pretty printing with c++ +// pretty pretty_printing with c++ // #ifndef SOI_PRETTY @@ -11,14 +11,7 @@ #include "prettyprint.hpp" -namespace soi_h { - -template -inline typename std::enable_if< ::pretty_print::is_container::value, - std::basic_ostream &>::type -pretty_print(std::basic_ostream & stream, const T & container) { - return stream << ::pretty_print::print_container_helper(container); -} +namespace soi { template std::basic_ostream & @@ -65,12 +58,18 @@ pretty_print(std::basic_ostream & stream, char c) { } template -inline typename std::enable_if< !::pretty_print::is_container::value, +inline typename std::enable_if< !::soi::is_container::value, std::basic_ostream &>::type pretty_print(std::basic_ostream & stream, const T& x) { return stream << x; } + +template +std::basic_ostream & +print(std::basic_ostream & stream, const T& x) { + return pretty_print(stream, x); +} } #endif // SOI_PRETTY diff --git a/include/soi b/include/soi index 5e4d9e6..a3e57c8 100644 --- a/include/soi +++ b/include/soi @@ -8,7 +8,7 @@ #include #include "bits/soi-dbg.hpp" -namespace soi_h { +namespace soi { void check_for_eof() { if (!(std::cin >> std::ws).eof()) @@ -52,11 +52,11 @@ void initialize_debug() { std::atexit(noninteractive_check_eof) != 0) { std::cerr << "WARNING: soi.h -- registration of sanity check at exit failed\n"; } - soi_h::detail::dbg_init(); + soi::detail::dbg_init(); } -struct soi_h_initializer { - soi_h_initializer(bool release) { +struct soi_initializer { + soi_initializer(bool release) { if (release) { std::ios::sync_with_stdio(false); std::cin.tie(0); @@ -67,12 +67,12 @@ struct soi_h_initializer { }; #ifdef SOI_RELEASE -soi_h_initializer soi_h_initializer_{true}; +soi_initializer soi_initializer_{true}; #else -soi_h_initializer soi_h_initializer_{false}; +soi_initializer soi_initializer_{false}; #endif -} // end namespace soi_h +} // end namespace soi #include "bits/soi-deprecate.hpp" From 492a0f3c559c16a79a26159cb3a9f1b56e085c86 Mon Sep 17 00:00:00 2001 From: Johannes Kapfhammer Date: Sun, 6 Oct 2019 18:38:23 +0200 Subject: [PATCH 3/3] run clang-format --- include/bits/prettyprint.hpp | 560 ++++++++++++++++++--------------- include/bits/soi-dbg.hpp | 235 ++++++-------- include/bits/soi-deprecate.hpp | 73 +++-- include/bits/soi-pretty.hpp | 85 +++-- include/soi | 18 +- 5 files changed, 517 insertions(+), 454 deletions(-) diff --git a/include/bits/prettyprint.hpp b/include/bits/prettyprint.hpp index 52d720b..862ee3d 100644 --- a/include/bits/prettyprint.hpp +++ b/include/bits/prettyprint.hpp @@ -23,400 +23,446 @@ namespace soi { -template +template std::basic_ostream & -print(std::basic_ostream & stream, const T& x); +print(std::basic_ostream &stream, const T &x); -namespace detail -{ +namespace detail { // SFINAE type trait to detect whether T::const_iterator exists. -struct sfinae_base -{ - using yes = char; - using no = yes[2]; +struct sfinae_base { + using yes = char; + using no = yes[2]; }; -template -struct has_const_iterator : private sfinae_base -{ +template struct has_const_iterator : private sfinae_base { private: - template static yes & test(typename C::const_iterator*); - template static no & test(...); -public: - static const bool value = sizeof(test(nullptr)) == sizeof(yes); - using type = T; -}; - -template -struct has_begin_end : private sfinae_base -{ -private: - template - static yes & f(typename std::enable_if< - std::is_same(&C::begin)), - typename C::const_iterator(C::*)() const>::value>::type *); - - template static no & f(...); - - template - static yes & g(typename std::enable_if< - std::is_same(&C::end)), - typename C::const_iterator(C::*)() const>::value, void>::type*); - - template static no & g(...); + template static yes &test(typename C::const_iterator *); + template static no &test(...); public: - static bool const beg_value = sizeof(f(nullptr)) == sizeof(yes); - static bool const end_value = sizeof(g(nullptr)) == sizeof(yes); + static const bool value = sizeof(test(nullptr)) == sizeof(yes); + using type = T; }; -} // namespace detail +template struct has_begin_end : private sfinae_base { +private: + template + static yes & + f(typename std::enable_if< + std::is_same(&C::begin)), + typename C::const_iterator (C::*)() const>::value>::type *); + template static no &f(...); + + template + static yes & + g(typename std::enable_if< + std::is_same(&C::end)), + typename C::const_iterator (C::*)() const>::value, + void>::type *); + + template static no &g(...); + +public: + static bool const beg_value = sizeof(f(nullptr)) == sizeof(yes); + static bool const end_value = sizeof(g(nullptr)) == sizeof(yes); +}; + +} // namespace detail // Holds the delimiter values for a specific character type -template -struct delimiters_values -{ - using char_type = TChar; - const char_type * prefix; - const char_type * delimiter; - const char_type * postfix; +template 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 -struct delimiters -{ - using type = delimiters_values; - static const type values; +template struct delimiters { + using type = delimiters_values; + static const type values; }; - // 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 // be customized by specializing the nested template. -template , typename TDelimiters = delimiters> -struct pretty_print_container_helper -{ - using delimiters_type = TDelimiters; - using ostream_type = std::basic_ostream; +struct pretty_print_container_helper { + using delimiters_type = TDelimiters; + using ostream_type = std::basic_ostream; - template - struct pretty_printer - { - static void pretty_print_body(const U & c, ostream_type & stream) - { - using std::begin; - using std::end; + template struct pretty_printer { + static void pretty_print_body(const U &c, ostream_type &stream) { + using std::begin; + using std::end; - auto it = begin(c); - const auto the_end = end(c); + auto it = begin(c); + const auto the_end = end(c); - if (it != the_end) - { - for ( ; ; ) - { - ::soi::print(stream, *it); + if (it != the_end) { + for (;;) { + ::soi::print(stream, *it); - if (++it == the_end) break; + if (++it == the_end) + break; - if (delimiters_type::values.delimiter != NULL) - ::soi::print(stream, delimiters_type::values.delimiter); - } - } + if (delimiters_type::values.delimiter != NULL) + ::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::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::pretty_print_body(container_, stream); + + if (delimiters_type::values.postfix != NULL) + ::soi::print(stream, delimiters_type::values.postfix); + } private: - const T & container_; + const T &container_; }; // Specialization for pairs -template +template template -struct pretty_print_container_helper::pretty_printer> -{ - using ostream_type = typename pretty_print_container_helper::ostream_type; +struct pretty_print_container_helper< + T, TChar, TCharTraits, TDelimiters>::pretty_printer> { + using ostream_type = + typename pretty_print_container_helper::ostream_type; - static void pretty_print_body(const std::pair & c, ostream_type & stream) - { - ::soi::print(stream, c.first); - if (pretty_print_container_helper::delimiters_type::values.delimiter != NULL) - ::soi::print(stream, pretty_print_container_helper::delimiters_type::values.delimiter); - ::soi::print(stream, c.second); - } + static void pretty_print_body(const std::pair &c, + ostream_type &stream) { + ::soi::print(stream, c.first); + if (pretty_print_container_helper::delimiters_type::values + .delimiter != NULL) + ::soi::print( + stream, + pretty_print_container_helper::delimiters_type::values + .delimiter); + ::soi::print(stream, c.second); + } }; // Specialization for tuples -template -template -struct pretty_print_container_helper::pretty_printer> -{ - using ostream_type = typename pretty_print_container_helper::ostream_type; - using element_type = std::tuple; +template +template +struct pretty_print_container_helper< + T, TChar, TCharTraits, TDelimiters>::pretty_printer> { + using ostream_type = + typename pretty_print_container_helper::ostream_type; + using element_type = std::tuple; - template struct Int { }; + template struct Int {}; - static void pretty_print_body(const element_type & c, ostream_type & stream) - { - tuple_pretty_print(c, stream, Int<0>()); - } + static void pretty_print_body(const element_type &c, ostream_type &stream) { + tuple_pretty_print(c, stream, Int<0>()); + } - static void tuple_pretty_print(const element_type &, ostream_type &, Int) - { - } + static void tuple_pretty_print(const element_type &, ostream_type &, + Int) {} - static void tuple_pretty_print(const element_type & c, ostream_type & stream, - typename std::conditional, std::nullptr_t>::type) - { - ::soi::print(stream, std::get<0>(c)); - tuple_pretty_print(c, stream, Int<1>()); - } + static void + tuple_pretty_print(const element_type &c, ostream_type &stream, + typename std::conditional, + std::nullptr_t>::type) { + ::soi::print(stream, std::get<0>(c)); + tuple_pretty_print(c, stream, Int<1>()); + } - template - static void tuple_pretty_print(const element_type & c, ostream_type & stream, Int) - { - if (pretty_print_container_helper::delimiters_type::values.delimiter != NULL) - ::soi::print(stream, pretty_print_container_helper::delimiters_type::values.delimiter); + template + static void tuple_pretty_print(const element_type &c, ostream_type &stream, + Int) { + if (pretty_print_container_helper::delimiters_type::values + .delimiter != NULL) + ::soi::print( + stream, + pretty_print_container_helper::delimiters_type::values + .delimiter); - ::soi::print(stream, std::get(c)); + ::soi::print(stream, std::get(c)); - tuple_pretty_print(c, stream, Int()); - } + tuple_pretty_print(c, stream, Int()); + } }; // Pretty_Prints a pretty_print_container_helper to the specified stream. -template -inline std::basic_ostream & pretty_print( - std::basic_ostream & stream, - const pretty_print_container_helper & helper) -{ - helper(stream); - return stream; +template +inline std::basic_ostream & +pretty_print(std::basic_ostream &stream, + const pretty_print_container_helper &helper) { + helper(stream); + return stream; } - -// Basic is_container template; specialize to derive from std::true_type for all desired container types +// Basic is_container template; specialize to derive from std::true_type for all +// desired container types template -struct is_container : public std::integral_constant::value && - detail::has_begin_end::beg_value && - detail::has_begin_end::end_value> { }; +struct is_container + : public std::integral_constant::value && + detail::has_begin_end::beg_value && + detail::has_begin_end::end_value> {}; template -struct is_container : std::true_type { }; +struct is_container : std::true_type {}; -template -struct is_container : std::false_type { }; +template struct is_container : std::false_type {}; -template -struct is_container> : std::true_type { }; +template struct is_container> : std::true_type {}; template -struct is_container> : std::true_type { }; - -template -struct is_container> : std::true_type { }; +struct is_container> : std::true_type {}; +template +struct is_container> : std::true_type {}; // Default delimiters -template struct delimiters { static const delimiters_values values; }; -template const delimiters_values delimiters::values = { "[", ", ", "]" }; -template struct delimiters { static const delimiters_values values; }; -template const delimiters_values delimiters::values = { L"[", L", ", L"]" }; - +template struct delimiters { + static const delimiters_values values; +}; +template +const delimiters_values delimiters::values = {"[", ", ", "]"}; +template struct delimiters { + static const delimiters_values values; +}; +template +const delimiters_values delimiters::values = {L"[", L", ", + L"]"}; // Delimiters for (multi)set and unordered_(multi)set template -struct delimiters< ::std::set, char> { static const delimiters_values values; }; +struct delimiters<::std::set, char> { + static const delimiters_values values; +}; template -const delimiters_values delimiters< ::std::set, char>::values = { "{", ", ", "}" }; +const delimiters_values + delimiters<::std::set, char>::values = {"{", ", ", + "}"}; template -struct delimiters< ::std::set, wchar_t> { static const delimiters_values values; }; +struct delimiters<::std::set, wchar_t> { + static const delimiters_values values; +}; template -const delimiters_values delimiters< ::std::set, wchar_t>::values = { L"{", L", ", L"}" }; +const delimiters_values + delimiters<::std::set, wchar_t>::values = { + L"{", L", ", L"}"}; template -struct delimiters< ::std::multiset, char> { static const delimiters_values values; }; +struct delimiters<::std::multiset, char> { + static const delimiters_values values; +}; template -const delimiters_values delimiters< ::std::multiset, char>::values = { "{", ", ", "}" }; +const delimiters_values delimiters<::std::multiset, + char>::values = {"{", ", ", "}"}; template -struct delimiters< ::std::multiset, wchar_t> { static const delimiters_values values; }; +struct delimiters<::std::multiset, wchar_t> { + static const delimiters_values values; +}; template -const delimiters_values delimiters< ::std::multiset, wchar_t>::values = { L"{", L", ", L"}" }; +const delimiters_values + delimiters<::std::multiset, wchar_t>::values = { + L"{", L", ", L"}"}; template -struct delimiters< ::std::unordered_set, char> { static const delimiters_values values; }; +struct delimiters<::std::unordered_set, char> { + static const delimiters_values values; +}; template -const delimiters_values delimiters< ::std::unordered_set, char>::values = { "{", ", ", "}" }; +const delimiters_values delimiters< + ::std::unordered_set, char>::values = { + "{", ", ", "}"}; template -struct delimiters< ::std::unordered_set, wchar_t> { static const delimiters_values values; }; +struct delimiters<::std::unordered_set, wchar_t> { + static const delimiters_values values; +}; template -const delimiters_values delimiters< ::std::unordered_set, wchar_t>::values = { L"{", L", ", L"}" }; +const delimiters_values delimiters< + ::std::unordered_set, wchar_t>::values = { + L"{", L", ", L"}"}; template -struct delimiters< ::std::unordered_multiset, char> { static const delimiters_values values; }; +struct delimiters<::std::unordered_multiset, + char> { + static const delimiters_values values; +}; template -const delimiters_values delimiters< ::std::unordered_multiset, char>::values = { "{", ", ", "}" }; +const delimiters_values delimiters< + ::std::unordered_multiset, char>::values = { + "{", ", ", "}"}; template -struct delimiters< ::std::unordered_multiset, wchar_t> { static const delimiters_values values; }; +struct delimiters<::std::unordered_multiset, + wchar_t> { + static const delimiters_values values; +}; template -const delimiters_values delimiters< ::std::unordered_multiset, wchar_t>::values = { L"{", L", ", L"}" }; - +const delimiters_values + delimiters<::std::unordered_multiset, + wchar_t>::values = {L"{", L", ", L"}"}; // Delimiters for pair and tuple -template struct delimiters, char> { static const delimiters_values values; }; -template const delimiters_values delimiters, char>::values = { "(", ", ", ")" }; -template struct delimiters< ::std::pair, wchar_t> { static const delimiters_values values; }; -template const delimiters_values delimiters< ::std::pair, wchar_t>::values = { L"(", L", ", L")" }; - -template struct delimiters, char> { static const delimiters_values values; }; -template const delimiters_values delimiters, char>::values = { "(", ", ", ")" }; -template struct delimiters< ::std::tuple, wchar_t> { static const delimiters_values values; }; -template const delimiters_values delimiters< ::std::tuple, wchar_t>::values = { L"(", L", ", L")" }; +template struct delimiters, char> { + static const delimiters_values values; +}; +template +const delimiters_values delimiters, char>::values = { + "(", ", ", ")"}; +template +struct delimiters<::std::pair, wchar_t> { + static const delimiters_values values; +}; +template +const delimiters_values + delimiters<::std::pair, wchar_t>::values = {L"(", L", ", L")"}; +template struct delimiters, char> { + static const delimiters_values values; +}; +template +const delimiters_values delimiters, char>::values = { + "(", ", ", ")"}; +template struct delimiters<::std::tuple, wchar_t> { + static const delimiters_values values; +}; +template +const delimiters_values + delimiters<::std::tuple, wchar_t>::values = {L"(", L", ", L")"}; // Type-erasing helper class for easy use of custom delimiters. -// Requires TCharTraits = std::char_traits and TChar = char or wchar_t, and MyDelims needs to be defined for TChar. -// Usage: "cout << pretty_pretty_print::custom_delims(x)". +// Requires TCharTraits = std::char_traits and TChar = char or wchar_t, +// and MyDelims needs to be defined for TChar. Usage: "cout << +// pretty_pretty_print::custom_delims(x)". -struct custom_delims_base -{ - virtual ~custom_delims_base() { } - virtual std::ostream & stream(::std::ostream &) = 0; - virtual std::wostream & stream(::std::wostream &) = 0; +struct custom_delims_base { + virtual ~custom_delims_base() {} + virtual std::ostream &stream(::std::ostream &) = 0; + virtual std::wostream &stream(::std::wostream &) = 0; }; template -struct custom_delims_wrapper : custom_delims_base -{ - custom_delims_wrapper(const T & t_) : t(t_) { } +struct custom_delims_wrapper : custom_delims_base { + custom_delims_wrapper(const T &t_) : t(t_) {} - std::ostream & stream(std::ostream & s) - { - return pretty_print(s, pretty_print_container_helper, Delims>(t)); - } + std::ostream &stream(std::ostream &s) { + return pretty_print( + s, + pretty_print_container_helper, Delims>( + t)); + } - std::wostream & stream(std::wostream & s) - { - return pretty_print(s, pretty_print_container_helper, Delims>(t)); - } + std::wostream &stream(std::wostream &s) { + return pretty_print( + s, pretty_print_container_helper, + Delims>(t)); + } private: - const T & t; + const T &t; }; -template -struct custom_delims -{ - template - custom_delims(const Container & c) : base(new custom_delims_wrapper(c)) { } +template struct custom_delims { + template + custom_delims(const Container &c) + : base(new custom_delims_wrapper(c)) {} - std::unique_ptr base; + std::unique_ptr base; }; template -inline std::basic_ostream & pretty_print(std::basic_ostream & s, const custom_delims & p) -{ - return p.base->stream(s); +inline std::basic_ostream & +pretty_print(std::basic_ostream &s, + const custom_delims &p) { + return p.base->stream(s); } - // A wrapper for a C-style array given as pointer-plus-size. // Usage: std::cout << pretty_pretty_print_array(arr, n) << std::endl; -template -struct array_wrapper_n -{ - typedef const T * const_iterator; - typedef T value_type; +template 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; } + 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; + 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_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. -// Usage: std::cout << bucket_pretty_print(m, 4) << std::endl; (Pretty_Prints bucket 5 of container m.) +template struct bucket_pretty_print_wrapper { + typedef typename T::const_local_iterator const_iterator; + typedef typename T::size_type size_type; -template -struct bucket_pretty_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 begin() const - { - return m_map.cbegin(n); - } + const_iterator end() const { return m_map.cend(n); } - const_iterator end() const - { - return m_map.cend(n); - } - - bucket_pretty_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { } + bucket_pretty_print_wrapper(const T &m, size_type bucket) + : m_map(m), n(bucket) {} private: - const T & m_map; - const size_type n; + const T &m_map; + const size_type n; }; -} // namespace soi - +} // namespace soi /* // Global accessor functions for the convenience wrappers template -inline pretty_pretty_print::array_wrapper_n pretty_pretty_print_array(const T * const a, size_t n) +inline pretty_pretty_print::array_wrapper_n pretty_pretty_print_array(const T +* const a, size_t n) { return pretty_pretty_print::array_wrapper_n(a, n); } @@ -433,18 +479,18 @@ return pretty_pretty_print::bucket_pretty_print_wrapper(m, n); */ -namespace soi -{ +namespace soi { // Pretty_Prints a container to the stream using default delimiters -template -inline typename std::enable_if< ::soi::is_container::value, - std::basic_ostream &>::type -pretty_print(std::basic_ostream & stream, const T & container) -{ - return ::soi::print(stream, ::soi::pretty_print_container_helper(container)); -} +template +inline typename std::enable_if<::soi::is_container::value, + std::basic_ostream &>::type +pretty_print(std::basic_ostream &stream, + const T &container) { + return ::soi::print( + stream, + ::soi::pretty_print_container_helper(container)); } +} // namespace soi - -#endif // SOI_PRETTY_PRETTY_PRINT +#endif // SOI_PRETTY_PRETTY_PRINT diff --git a/include/bits/soi-dbg.hpp b/include/bits/soi-dbg.hpp index d3544c7..cbb47a4 100644 --- a/include/bits/soi-dbg.hpp +++ b/include/bits/soi-dbg.hpp @@ -11,11 +11,11 @@ #define SOI_DBG #include -#include #include -#include #include +#include #include +#include #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #include @@ -31,113 +31,99 @@ namespace detail { // detecting the type name: https://stackoverflow.com/a/20170989 #ifndef _MSC_VER -# if __cplusplus < 201103 -# define CONSTEXPR11_TN -# define CONSTEXPR14_TN -# define NOEXCEPT_TN -# elif __cplusplus < 201402 -# define CONSTEXPR11_TN constexpr -# define CONSTEXPR14_TN -# define NOEXCEPT_TN noexcept -# else -# define CONSTEXPR11_TN constexpr -# define CONSTEXPR14_TN constexpr -# define NOEXCEPT_TN noexcept -# endif -#else // _MSC_VER -# if _MSC_VER < 1900 -# define CONSTEXPR11_TN -# define CONSTEXPR14_TN -# define NOEXCEPT_TN -# elif _MSC_VER < 2000 -# define CONSTEXPR11_TN constexpr -# define CONSTEXPR14_TN -# define NOEXCEPT_TN noexcept -# else -# define CONSTEXPR11_TN constexpr -# define CONSTEXPR14_TN constexpr -# define NOEXCEPT_TN noexcept -# endif -#endif // _MSC_VER +#if __cplusplus < 201103 +#define CONSTEXPR11_TN +#define CONSTEXPR14_TN +#define NOEXCEPT_TN +#elif __cplusplus < 201402 +#define CONSTEXPR11_TN constexpr +#define CONSTEXPR14_TN +#define NOEXCEPT_TN noexcept +#else +#define CONSTEXPR11_TN constexpr +#define CONSTEXPR14_TN constexpr +#define NOEXCEPT_TN noexcept +#endif +#else // _MSC_VER +#if _MSC_VER < 1900 +#define CONSTEXPR11_TN +#define CONSTEXPR14_TN +#define NOEXCEPT_TN +#elif _MSC_VER < 2000 +#define CONSTEXPR11_TN constexpr +#define CONSTEXPR14_TN +#define NOEXCEPT_TN noexcept +#else +#define CONSTEXPR11_TN constexpr +#define CONSTEXPR14_TN constexpr +#define NOEXCEPT_TN noexcept +#endif +#endif // _MSC_VER class static_string { - const char* const p_; - const std::size_t sz_; + const char *const p_; + const std::size_t sz_; public: - typedef const char* const_iterator; + typedef const char *const_iterator; - template - CONSTEXPR11_TN static_string(const char(&a)[N]) NOEXCEPT_TN - : p_(a) - , sz_(N-1) - {} + template + CONSTEXPR11_TN static_string(const char (&a)[N]) NOEXCEPT_TN : p_(a), + sz_(N - 1) {} - CONSTEXPR11_TN static_string(const char* p, std::size_t N) NOEXCEPT_TN - : p_(p) - , sz_(N) - {} + CONSTEXPR11_TN static_string(const char *p, std::size_t N) NOEXCEPT_TN + : p_(p), + sz_(N) {} - CONSTEXPR11_TN const char* data() const NOEXCEPT_TN {return p_;} - CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN {return sz_;} + CONSTEXPR11_TN const char *data() const NOEXCEPT_TN { return p_; } + 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 end() const NOEXCEPT_TN {return p_ + sz_;} + CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN { return p_; } + CONSTEXPR11_TN const_iterator end() const NOEXCEPT_TN { return p_ + sz_; } - CONSTEXPR11_TN char operator[](std::size_t n) const - { - return n < sz_ ? p_[n] : throw std::out_of_range("static_string"); - } + CONSTEXPR11_TN char operator[](std::size_t n) const { + return n < sz_ ? p_[n] : throw std::out_of_range("static_string"); + } }; -inline -std::ostream& -operator<<(std::ostream& os, static_string const& s) -{ - return os.write(s.data(), s.size()); +inline std::ostream &operator<<(std::ostream &os, static_string const &s) { + return os.write(s.data(), s.size()); } -template -CONSTEXPR14_TN -static_string -type_name() -{ - const int k = sizeof("constexpr soi::detail:: T")/sizeof(char); +template CONSTEXPR14_TN static_string type_name() { + const int k = sizeof("constexpr soi::detail:: T") / sizeof(char); #ifdef __clang__ - static_string p = __PRETTY_FUNCTION__; - return static_string(p.data() + 31 + k, p.size() - 31 - k - 1); + static_string p = __PRETTY_FUNCTION__; + return static_string(p.data() + 31 + k, p.size() - 31 - k - 1); #elif defined(__GNUC__) - static_string p = __PRETTY_FUNCTION__; -# if __cplusplus < 201402 - return static_string(p.data() + 36 + k, p.size() - 36 - k - 1); -# else - return static_string(p.data() + 46 + k, p.size() - 46 - k - 1); -# endif + static_string p = __PRETTY_FUNCTION__; +#if __cplusplus < 201402 + return static_string(p.data() + 36 + k, p.size() - 36 - k - 1); +#else + return static_string(p.data() + 46 + k, p.size() - 46 - k - 1); +#endif #elif defined(_MSC_VER) - static_string p = __FUNCSIG__; - return static_string(p.data() + 38 + k, p.size() - 38 - k - 7); + static_string p = __FUNCSIG__; + return static_string(p.data() + 38 + k, p.size() - 38 - k - 7); #endif } 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 -CONSTEXPR14_TN -static_string -sanitized_type_name() { +template CONSTEXPR14_TN static_string sanitized_type_name() { CONSTEXPR14_TN static_string t = type_name(); CONSTEXPR14_TN std::size_t offset = - is_prefix_of("std::__debug::", t.data()) ? sizeof("std::__debug::")-1 : - is_prefix_of("std::", t.data()) ? sizeof("std::")-1 : - 0; - return - is_prefix_of("std::__cxx11::basic_string", t.data()) ? - static_string(type_string, sizeof(type_string)-2) : - static_string(t.data()+offset, t.size()-offset); + is_prefix_of("std::__debug::", t.data()) + ? sizeof("std::__debug::") - 1 + : is_prefix_of("std::", t.data()) ? sizeof("std::") - 1 : 0; + return is_prefix_of("std::__cxx11::basic_string", t.data()) + ? static_string(type_string, sizeof(type_string) - 2) + : static_string(t.data() + offset, t.size() - offset); } // ---------------------------------------------------------------------------- @@ -152,7 +138,7 @@ bool tty_supports_colors() { } 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")) return 1; if (!std::strcmp(color_enabled, "0")) @@ -172,12 +158,12 @@ bool are_colors_enabled() { // init and static variables static bool colors_enabled = false; -static const char* ANSI_DEBUG = ""; -static const char* ANSI_EXPRESSION = ""; -static const char* ANSI_VALUE = ""; -static const char* ANSI_TYPE = ""; -static const char* ANSI_MESSAGE = ""; -static const char* ANSI_RESET = ""; +static const char *ANSI_DEBUG = ""; +static const char *ANSI_EXPRESSION = ""; +static const char *ANSI_VALUE = ""; +static const char *ANSI_TYPE = ""; +static const char *ANSI_MESSAGE = ""; +static const char *ANSI_RESET = ""; void dbg_init(bool with_colors) { if (with_colors) { @@ -199,70 +185,51 @@ void dbg_init(bool with_colors) { } } -void dbg_init() { - dbg_init(are_colors_enabled()); -} +void dbg_init() { dbg_init(are_colors_enabled()); } // ---------------------------------------------------------------------------- // printer template -T&& dbg_print(T&& value, - static_string const& type, - char const* file, - int line, - char const* function_name, - char const* expression) { - const T& ref = value; - std::stringstream value_buffer; // avoid nesting of dbg macros within print functinos +T &&dbg_print(T &&value, static_string const &type, char const *file, int line, + char const *function_name, char const *expression) { + const T &ref = value; + std::stringstream + value_buffer; // avoid nesting of dbg macros within print functinos soi::print(value_buffer, ref); - std::cerr << ANSI_DEBUG - << "[" << file << ":" << line - << " (" << function_name << ")] " << ANSI_RESET - << ANSI_EXPRESSION << expression << ANSI_RESET - << " = " - << ANSI_VALUE << value_buffer.rdbuf() << ANSI_RESET - << " (" << ANSI_TYPE << type << ANSI_RESET << ")" + std::cerr << ANSI_DEBUG << "[" << file << ":" << line << " (" << function_name + << ")] " << ANSI_RESET << ANSI_EXPRESSION << expression + << ANSI_RESET << " = " << ANSI_VALUE << value_buffer.rdbuf() + << ANSI_RESET << " (" << ANSI_TYPE << type << ANSI_RESET << ")" << '\n'; return std::forward(value); } -template -auto dbg_print(const char (&msg)[N], - static_string const&, - char const* file, - int line, - char const* function_name, - char const* expression) -> decltype(msg) { - std::cerr << ANSI_DEBUG - << "[" << file << ":" << line - << " (" << function_name << ")] " << ANSI_RESET - << ANSI_MESSAGE << msg << ANSI_RESET - << '\n'; +template +auto dbg_print(const char (&msg)[N], static_string const &, char const *file, + int line, char const *function_name, char const *expression) + -> decltype(msg) { + std::cerr << ANSI_DEBUG << "[" << file << ":" << line << " (" << function_name + << ")] " << ANSI_RESET << ANSI_MESSAGE << msg << ANSI_RESET << '\n'; return msg; } -template -T&& identity(T&& t) { - return std::forward(t); -} +template T &&identity(T &&t) { return std::forward(t); } } // end namespace detail -} // end namespace dbg_macro +} // namespace soi #ifdef SOI_RELEASE #define dbg(...) dbg_macro::identity(__VA_ARGS__) #else -#define dbg(...) \ - soi::detail::dbg_print((__VA_ARGS__), \ - soi::detail::sanitized_type_name(), \ - __FILE__, \ - __LINE__, \ - __func__, \ - #__VA_ARGS__) +#define dbg(...) \ + soi::detail::dbg_print( \ + (__VA_ARGS__), \ + soi::detail::sanitized_type_name(), __FILE__, \ + __LINE__, __func__, #__VA_ARGS__) #endif -#endif // SOI_DBG +#endif // SOI_DBG diff --git a/include/bits/soi-deprecate.hpp b/include/bits/soi-deprecate.hpp index eae61d3..e6676ae 100644 --- a/include/bits/soi-deprecate.hpp +++ b/include/bits/soi-deprecate.hpp @@ -1,24 +1,32 @@ #pragma GCC diagnostic error "-Wdeprecated-declarations" -struct 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); +struct 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 printf printf_is_evil #define fprintf fprintf_is_evil #define sprintf sprintf_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 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, ...); +[[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 +snprintf(char *buffer, std::size_t buf_size, const char *format, ...); #define scanf scanf_is_evil #define fscanf fscanf_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 fscanf(std::FILE *stream, const char *format, ...); -[[deprecated("scanf is evil. Use cin.")]] int sscanf(const char *buffer, const char *format, ...); +[[deprecated("scanf is evil. Use cin.")]] int fscanf(std::FILE *stream, + const char *format, ...); +[[deprecated("scanf is evil. Use cin.")]] int sscanf(const char *buffer, + const char *format, ...); #define puts puts_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 fwrite fwrite_is_evil [[deprecated(" is evil. Use cin/cout.")]] int puts(const char *str); -[[deprecated(" is evil. Use cin/cout.")]] int fputs(const char *str, FILE *stream); -[[deprecated(" is evil. Use cin/cout.")]] char *fgets(char *str, int count, FILE *stream); -[[deprecated(" is evil. Use cin/cout.")]] std::FILE *freopen(const char *filename, const char *mode, std::FILE *stream); -[[deprecated(" is evil. Use cin/cout.")]] std::FILE *fopen(const char *filename, const char *mode); -[[deprecated(" is evil. Use cin/cout.")]] int fclose(std::FILE *stream); -[[deprecated(" is evil. Use cin/cout.")]] int fflush(std::FILE *stream); +[[deprecated(" is evil. Use cin/cout.")]] int fputs(const char *str, + FILE *stream); +[[deprecated(" is evil. Use cin/cout.")]] char * +fgets(char *str, int count, FILE *stream); +[[deprecated(" is evil. Use cin/cout.")]] std::FILE * +freopen(const char *filename, const char *mode, std::FILE *stream); +[[deprecated(" is evil. Use cin/cout.")]] std::FILE * +fopen(const char *filename, const char *mode); +[[deprecated(" is evil. Use cin/cout.")]] int +fclose(std::FILE *stream); +[[deprecated(" is evil. Use cin/cout.")]] int +fflush(std::FILE *stream); [[deprecated(" is evil. Use cin/cout.")]] int getchar(); [[deprecated(" is evil. Use cin/cout.")]] int fgetc(std::FILE *stream); [[deprecated(" is evil. Use cin/cout.")]] int getc(std::FILE *stream); -[[deprecated(" is evil. Use cin/cout.")]] void setbuf(std::FILE *stream, char *buffer); -[[deprecated(" is evil. Use cin/cout.")]] int setvbuf(std::FILE *stream, char *buffer, int mode, std::size_t size); -[[deprecated(" is evil. Use cin/cout.")]] std::size_t fread(void *buffer, std::size_t size, std::size_t count, std::FILE *stream); -[[deprecated(" is evil. Use cin/cout.")]] std::size_t fwrite(const void *buffer, std::size_t size, std::size_t count, std::FILE *stream); +[[deprecated(" is evil. Use cin/cout.")]] void +setbuf(std::FILE *stream, char *buffer); +[[deprecated(" is evil. Use cin/cout.")]] int +setvbuf(std::FILE *stream, char *buffer, int mode, std::size_t size); +[[deprecated(" is evil. Use cin/cout.")]] std::size_t +fread(void *buffer, std::size_t size, std::size_t count, std::FILE *stream); +[[deprecated(" 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 calloc calloc_is_evil #define realloc realloc_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 *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("malloc/free is evil. Use a vector.")]] void * +malloc(std::size_t size); +[[deprecated("malloc/free is evil. Use a vector.")]] void * +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("delete is evil. Use a vector.")]] void operator delete(void *ptr) noexcept; +[[deprecated("new is evil. Use a vector.")]] void * +operator new(std::size_t sz); +[[deprecated("delete is evil. Use a vector.")]] void +operator delete(void *ptr) noexcept; diff --git a/include/bits/soi-pretty.hpp b/include/bits/soi-pretty.hpp index 13925a1..0cd802e 100644 --- a/include/bits/soi-pretty.hpp +++ b/include/bits/soi-pretty.hpp @@ -13,63 +13,88 @@ namespace soi { -template +template std::basic_ostream & -pretty_print(std::basic_ostream & stream, const bool& x) { +pretty_print(std::basic_ostream &stream, const bool &x) { return stream << (x ? "true" : "false"); } namespace detail { -template -void escape_char(std::basic_ostream & stream, char c) { +template +void escape_char(std::basic_ostream &stream, char c) { switch (c) { - case '\a': stream << "\\a"; break; - case '\b': stream << "\\b"; break; - case '\t': stream << "\\t"; break; - case '\n': stream << "\\n"; break; - 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; + case '\a': + stream << "\\a"; + break; + case '\b': + stream << "\\b"; + break; + case '\t': + stream << "\\t"; + break; + case '\n': + stream << "\\n"; + break; + 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 +template std::basic_ostream & -pretty_print(std::basic_ostream & stream, const std::string& x) { +pretty_print(std::basic_ostream &stream, + const std::string &x) { stream << "\""; for (char c : x) detail::escape_char(stream, c); return stream << "\""; } -template +template std::basic_ostream & -pretty_print(std::basic_ostream & stream, char c) { +pretty_print(std::basic_ostream &stream, char c) { stream << "'"; detail::escape_char(stream, c); return stream << "'"; } -template -inline typename std::enable_if< !::soi::is_container::value, - std::basic_ostream &>::type -pretty_print(std::basic_ostream & stream, const T& x) { +template +inline typename std::enable_if::value, + std::basic_ostream &>::type +pretty_print(std::basic_ostream &stream, const T &x) { return stream << x; } - -template +template std::basic_ostream & -print(std::basic_ostream & stream, const T& x) { +print(std::basic_ostream &stream, const T &x) { return pretty_print(stream, x); } -} +} // namespace soi #endif // SOI_PRETTY diff --git a/include/soi b/include/soi index a3e57c8..8e3c092 100644 --- a/include/soi +++ b/include/soi @@ -5,20 +5,20 @@ have to understand every concept all at once. */ -#include #include "bits/soi-dbg.hpp" +#include namespace soi { void check_for_eof() { - if (!(std::cin >> std::ws).eof()) - std::cerr << "WARNING: didn't read the whole input\n"; + if (!(std::cin >> std::ws).eof()) + std::cerr << "WARNING: didn't read the whole input\n"; } void noninteractive_check_eof() { // make symbol 0x1A (Ctrl+Z) a whitespace struct console_ctype : std::ctype { - static const mask* get_table() { + static const mask *get_table() { static const std::array table = []() { std::array table; std::copy(classic_table(), classic_table() + table_size, table.begin()); @@ -27,14 +27,14 @@ void noninteractive_check_eof() { }(); 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)); 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")) return true; if (!std::strcmp(eofcheck_enabled, "0")) @@ -48,9 +48,9 @@ void initialize_debug() { std::cin.exceptions(std::ifstream::failbit | std::ifstream::badbit); std::ios::sync_with_stdio(false); - if (should_check_for_eof() && - std::atexit(noninteractive_check_eof) != 0) { - std::cerr << "WARNING: soi.h -- registration of sanity check at exit failed\n"; + if (should_check_for_eof() && std::atexit(noninteractive_check_eof) != 0) { + std::cerr + << "WARNING: soi.h -- registration of sanity check at exit failed\n"; } soi::detail::dbg_init(); }