From 4d25fc25c4fc769784e161f05614f1783ef78724 Mon Sep 17 00:00:00 2001 From: Johannes Kapfhammer Date: Sun, 6 Oct 2019 18:37:37 +0200 Subject: [PATCH] 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"