Decouple appender from back_insert_iterator
This commit is contained in:
parent
242bcaec04
commit
c9d233c0a4
@ -11,7 +11,7 @@
|
||||
#include <cstddef> // std::byte
|
||||
#include <cstdio> // std::FILE
|
||||
#include <cstring> // std::strlen
|
||||
#include <iterator> // std::back_insert_iterator
|
||||
#include <iterator> // DEPRECATED!
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
@ -1099,16 +1099,27 @@ using has_formatter =
|
||||
|
||||
// An output iterator that appends to a buffer.
|
||||
// It is used to reduce symbol sizes for the common case.
|
||||
class appender : public std::back_insert_iterator<detail::buffer<char>> {
|
||||
using base = std::back_insert_iterator<detail::buffer<char>>;
|
||||
class appender {
|
||||
private:
|
||||
detail::buffer<char>* buffer_;
|
||||
|
||||
friend auto get_container(appender app) -> detail::buffer<char>& {
|
||||
return *app.buffer_;
|
||||
}
|
||||
|
||||
public:
|
||||
using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator;
|
||||
appender(base it) noexcept : base(it) {}
|
||||
using difference_type = ptrdiff_t;
|
||||
FMT_UNCHECKED_ITERATOR(appender);
|
||||
|
||||
auto operator++() noexcept -> appender& { return *this; }
|
||||
auto operator++(int) noexcept -> appender { return *this; }
|
||||
appender(detail::buffer<char>& buf) : buffer_(&buf) {}
|
||||
|
||||
auto operator=(char c) -> appender& {
|
||||
buffer_->push_back(c);
|
||||
return *this;
|
||||
}
|
||||
auto operator*() -> appender& {return *this;}
|
||||
auto operator++() -> appender& { return *this; }
|
||||
auto operator++(int) -> appender { return *this; }
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@ -1545,6 +1556,8 @@ template <typename...> using void_t = void;
|
||||
template <typename It, typename T, typename Enable = void>
|
||||
struct is_output_iterator : std::false_type {};
|
||||
|
||||
template <> struct is_output_iterator<appender, char> : std::true_type {};
|
||||
|
||||
template <typename It, typename T>
|
||||
struct is_output_iterator<
|
||||
It, T,
|
||||
|
@ -262,6 +262,14 @@ inline auto ctzll(uint64_t x) -> int {
|
||||
FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct iterator_traits<fmt::appender> {
|
||||
using value_type = void;
|
||||
using iterator_category = std::output_iterator_tag;
|
||||
};
|
||||
}
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include <algorithm> // std::copy_n
|
||||
#include <climits> // INT_MAX
|
||||
#include <cstring> // std::strlen
|
||||
#include <functional> // std::equal_to
|
||||
@ -33,6 +32,11 @@ using testing::Return;
|
||||
# error core-test includes format.h
|
||||
#endif
|
||||
|
||||
fmt::appender copy(fmt::string_view s, fmt::appender out) {
|
||||
for (char c : s) *out++ = c;
|
||||
return out;
|
||||
}
|
||||
|
||||
TEST(string_view_test, value_type) {
|
||||
static_assert(std::is_same<string_view::value_type, char>::value, "");
|
||||
}
|
||||
@ -102,16 +106,6 @@ TEST(core_test, is_output_iterator) {
|
||||
}
|
||||
|
||||
TEST(core_test, buffer_appender) {
|
||||
// back_insert_iterator is not default-constructible before C++20, so
|
||||
// buffer_appender can only be default-constructible when back_insert_iterator
|
||||
// is.
|
||||
static_assert(
|
||||
std::is_default_constructible<
|
||||
std::back_insert_iterator<fmt::detail::buffer<char>>>::value ==
|
||||
std::is_default_constructible<
|
||||
fmt::detail::buffer_appender<char>>::value,
|
||||
"");
|
||||
|
||||
#ifdef __cpp_lib_ranges
|
||||
static_assert(std::output_iterator<fmt::detail::buffer_appender<char>, char>);
|
||||
#endif
|
||||
@ -297,8 +291,7 @@ template <typename Char> struct formatter<test_struct, Char> {
|
||||
}
|
||||
|
||||
auto format(test_struct, format_context& ctx) const -> decltype(ctx.out()) {
|
||||
auto test = string_view("test");
|
||||
return std::copy_n(test.data(), test.size(), ctx.out());
|
||||
return copy("test", ctx.out());
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
@ -619,8 +612,7 @@ template <> struct formatter<const_formattable> {
|
||||
|
||||
auto format(const const_formattable&, format_context& ctx)
|
||||
-> decltype(ctx.out()) {
|
||||
auto test = string_view("test");
|
||||
return std::copy_n(test.data(), test.size(), ctx.out());
|
||||
return copy("test", ctx.out());
|
||||
}
|
||||
};
|
||||
|
||||
@ -631,8 +623,7 @@ template <> struct formatter<nonconst_formattable> {
|
||||
|
||||
auto format(nonconst_formattable&, format_context& ctx)
|
||||
-> decltype(ctx.out()) {
|
||||
auto test = string_view("test");
|
||||
return std::copy_n(test.data(), test.size(), ctx.out());
|
||||
return copy("test", ctx.out());
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
@ -653,8 +644,7 @@ template <> struct formatter<convertible_to_pointer_formattable> {
|
||||
|
||||
auto format(convertible_to_pointer_formattable, format_context& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto test = string_view("test");
|
||||
return std::copy_n(test.data(), test.size(), ctx.out());
|
||||
return copy("test", ctx.out());
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
@ -732,7 +722,7 @@ template <> struct formatter<convertible_to_int> {
|
||||
}
|
||||
auto format(convertible_to_int, format_context& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return std::copy_n("foo", 3, ctx.out());
|
||||
return copy("foo", ctx.out());
|
||||
}
|
||||
};
|
||||
|
||||
@ -742,7 +732,7 @@ template <> struct formatter<convertible_to_cstring> {
|
||||
}
|
||||
auto format(convertible_to_cstring, format_context& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return std::copy_n("bar", 3, ctx.out());
|
||||
return copy("bar", ctx.out());
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
@ -853,8 +843,7 @@ template <> struct formatter<its_a_trap> {
|
||||
}
|
||||
|
||||
auto format(its_a_trap, format_context& ctx) const -> decltype(ctx.out()) {
|
||||
auto s = string_view("42");
|
||||
return std::copy(s.begin(), s.end(), ctx.out());
|
||||
return copy("42", ctx.out());
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
|
Loading…
Reference in New Issue
Block a user