From f2c55f6bb8a487fbb524a992da63fd0f94045b41 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 3 Jan 2024 05:59:48 -0800 Subject: [PATCH] Remove dependency on back_insert_iterator --- include/fmt/core.h | 71 +++++++++++++++++++++++++++----------------- include/fmt/format.h | 24 ++++++++++++--- include/fmt/xchar.h | 2 +- 3 files changed, 65 insertions(+), 32 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index d82948b7..2d71424e 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -309,6 +309,36 @@ struct monostate { constexpr monostate() {} }; +// An implementation of back_insert_iterator to avoid dependency on . +template class back_insert_iterator { + private: + Container* container_; + + friend auto get_container(back_insert_iterator it) -> Container& { + return *it.container_; + } + + public: + using difference_type = ptrdiff_t; + FMT_UNCHECKED_ITERATOR(back_insert_iterator); + + explicit back_insert_iterator(Container& c) : container_(&c) {} + + auto operator=(const typename Container::value_type& value) + -> back_insert_iterator& { + container_->push_back(value); + return *this; + } + auto operator*() -> back_insert_iterator& { return *this; } + auto operator++() -> back_insert_iterator& { return *this; } + auto operator++(int) -> back_insert_iterator { return *this; } +}; + +template +auto back_inserter(Container& c) -> back_insert_iterator { + return {c}; +} + // An enable_if helper to be used in template parameters which results in much // shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed // to workaround a bug in MSVC 2019 (see #1140 and #1186). @@ -780,18 +810,6 @@ class compile_parse_context : public basic_format_parse_context { } }; -// Extracts a reference to the container from back_insert_iterator. -template -inline auto get_container(std::back_insert_iterator it) - -> Container& { - using base = std::back_insert_iterator; - struct accessor : base { - accessor(base b) : base(b) {} - using base::container; - }; - return *accessor(it).container; -} - template FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out) -> OutputIt { @@ -1012,7 +1030,7 @@ template class iterator_buffer final : public buffer { // A buffer that writes to a container with the contiguous storage. template -class iterator_buffer, +class iterator_buffer, enable_if_t::value, typename Container::value_type>> final : public buffer { @@ -1029,11 +1047,11 @@ class iterator_buffer, public: explicit iterator_buffer(Container& c) : buffer(grow, c.size()), container_(c) {} - explicit iterator_buffer(std::back_insert_iterator out, size_t = 0) + explicit iterator_buffer(back_insert_iterator out, size_t = 0) : iterator_buffer(get_container(out)) {} - auto out() -> std::back_insert_iterator { - return std::back_inserter(container_); + auto out() -> back_insert_iterator { + return fmt::back_inserter(container_); } }; @@ -1097,8 +1115,8 @@ template using has_formatter = std::is_constructible>; -// An output iterator that appends to a buffer. -// It is used to reduce symbol sizes for the common case. +// An output iterator that appends to a buffer. It is used instead of +// back_insert_iterator to reduce symbol sizes for the common case. class appender { private: detail::buffer* buffer_; @@ -1117,7 +1135,7 @@ class appender { buffer_->push_back(c); return *this; } - auto operator*() -> appender& {return *this;} + auto operator*() -> appender& { return *this; } auto operator++() -> appender& { return *this; } auto operator++(int) -> appender { return *this; } }; @@ -1142,7 +1160,7 @@ constexpr auto has_const_formatter() -> bool { template using buffer_appender = conditional_t::value, appender, - std::back_insert_iterator>>; + back_insert_iterator>>; // Maps an output iterator to a buffer. template @@ -1151,7 +1169,7 @@ auto get_buffer(OutputIt out) -> iterator_buffer { } template , Buf>::value)> -auto get_buffer(std::back_insert_iterator out) -> buffer& { +auto get_buffer(back_insert_iterator out) -> buffer& { return get_container(out); } @@ -1531,9 +1549,8 @@ auto copy_str(InputIt begin, InputIt end, appender out) -> appender { return out; } template -auto copy_str(InputIt begin, InputIt end, - std::back_insert_iterator out) - -> std::back_insert_iterator { +auto copy_str(InputIt begin, InputIt end, back_insert_iterator out) + -> back_insert_iterator { get_container(out).append(begin, end); return out; } @@ -1567,7 +1584,7 @@ struct is_output_iterator< template struct is_back_insert_iterator : std::false_type {}; template -struct is_back_insert_iterator> +struct is_back_insert_iterator> : std::true_type {}; // A type-erased reference to an std::locale to avoid a heavy include. @@ -2726,7 +2743,7 @@ void check_format_string(S format_str) { template struct vformat_args { using type = basic_format_args< - basic_format_context>, Char>>; + basic_format_context>, Char>>; }; template <> struct vformat_args { using type = format_args; @@ -2869,7 +2886,7 @@ auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt { **Example**:: auto out = std::vector(); - fmt::format_to(std::back_inserter(out), "{}", 42); + fmt::format_to(fmt::back_inserter(out), "{}", 42); \endrst */ template -struct iterator_traits { +template <> struct iterator_traits { using value_type = void; - using iterator_category = std::output_iterator_tag; + using iterator_category = std::output_iterator_tag; }; -} +template +struct iterator_traits> { + using value_type = void; + using iterator_category = std::output_iterator_tag; +}; +} // namespace std FMT_BEGIN_NAMESPACE namespace detail { @@ -500,6 +504,18 @@ FMT_INLINE void assume(bool condition) { #endif } +// Extracts a reference to the container from back_insert_iterator. +template +inline auto get_container(std::back_insert_iterator it) + -> Container& { + using base = std::back_insert_iterator; + struct accessor : base { + accessor(base b) : base(b) {} + using base::container; + }; + return *accessor(it).container; +} + // An approximation of iterator_t for pre-C++20 systems. template using iterator_t = decltype(std::begin(std::declval())); diff --git a/include/fmt/xchar.h b/include/fmt/xchar.h index de41aeea..1e791bb0 100644 --- a/include/fmt/xchar.h +++ b/include/fmt/xchar.h @@ -23,7 +23,7 @@ namespace detail { template using is_exotic_char = bool_constant::value>; -inline auto write_loc(std::back_insert_iterator> out, +inline auto write_loc(back_insert_iterator> out, loc_value value, const format_specs& specs, locale_ref loc) -> bool { #ifndef FMT_STATIC_THOUSANDS_SEPARATOR