forked from fmtlib/fmt
Remove dependency on back_insert_iterator
This commit is contained in:
@ -309,6 +309,36 @@ struct monostate {
|
|||||||
constexpr monostate() {}
|
constexpr monostate() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An implementation of back_insert_iterator to avoid dependency on <iterator>.
|
||||||
|
template <typename Container> 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 <typename Container>
|
||||||
|
auto back_inserter(Container& c) -> back_insert_iterator<Container> {
|
||||||
|
return {c};
|
||||||
|
}
|
||||||
|
|
||||||
// An enable_if helper to be used in template parameters which results in much
|
// 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
|
// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
|
||||||
// to workaround a bug in MSVC 2019 (see #1140 and #1186).
|
// to workaround a bug in MSVC 2019 (see #1140 and #1186).
|
||||||
@ -780,18 +810,6 @@ class compile_parse_context : public basic_format_parse_context<Char> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extracts a reference to the container from back_insert_iterator.
|
|
||||||
template <typename Container>
|
|
||||||
inline auto get_container(std::back_insert_iterator<Container> it)
|
|
||||||
-> Container& {
|
|
||||||
using base = std::back_insert_iterator<Container>;
|
|
||||||
struct accessor : base {
|
|
||||||
accessor(base b) : base(b) {}
|
|
||||||
using base::container;
|
|
||||||
};
|
|
||||||
return *accessor(it).container;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename InputIt, typename OutputIt>
|
template <typename Char, typename InputIt, typename OutputIt>
|
||||||
FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out)
|
FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out)
|
||||||
-> OutputIt {
|
-> OutputIt {
|
||||||
@ -1012,7 +1030,7 @@ template <typename T> class iterator_buffer<T*, T> final : public buffer<T> {
|
|||||||
|
|
||||||
// A buffer that writes to a container with the contiguous storage.
|
// A buffer that writes to a container with the contiguous storage.
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
class iterator_buffer<std::back_insert_iterator<Container>,
|
class iterator_buffer<back_insert_iterator<Container>,
|
||||||
enable_if_t<is_contiguous<Container>::value,
|
enable_if_t<is_contiguous<Container>::value,
|
||||||
typename Container::value_type>>
|
typename Container::value_type>>
|
||||||
final : public buffer<typename Container::value_type> {
|
final : public buffer<typename Container::value_type> {
|
||||||
@ -1029,11 +1047,11 @@ class iterator_buffer<std::back_insert_iterator<Container>,
|
|||||||
public:
|
public:
|
||||||
explicit iterator_buffer(Container& c)
|
explicit iterator_buffer(Container& c)
|
||||||
: buffer<value_type>(grow, c.size()), container_(c) {}
|
: buffer<value_type>(grow, c.size()), container_(c) {}
|
||||||
explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)
|
explicit iterator_buffer(back_insert_iterator<Container> out, size_t = 0)
|
||||||
: iterator_buffer(get_container(out)) {}
|
: iterator_buffer(get_container(out)) {}
|
||||||
|
|
||||||
auto out() -> std::back_insert_iterator<Container> {
|
auto out() -> back_insert_iterator<Container> {
|
||||||
return std::back_inserter(container_);
|
return fmt::back_inserter(container_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1097,8 +1115,8 @@ template <typename T, typename Context>
|
|||||||
using has_formatter =
|
using has_formatter =
|
||||||
std::is_constructible<typename Context::template formatter_type<T>>;
|
std::is_constructible<typename Context::template formatter_type<T>>;
|
||||||
|
|
||||||
// An output iterator that appends to a buffer.
|
// An output iterator that appends to a buffer. It is used instead of
|
||||||
// It is used to reduce symbol sizes for the common case.
|
// back_insert_iterator to reduce symbol sizes for the common case.
|
||||||
class appender {
|
class appender {
|
||||||
private:
|
private:
|
||||||
detail::buffer<char>* buffer_;
|
detail::buffer<char>* buffer_;
|
||||||
@ -1117,7 +1135,7 @@ class appender {
|
|||||||
buffer_->push_back(c);
|
buffer_->push_back(c);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
auto operator*() -> appender& {return *this;}
|
auto operator*() -> appender& { return *this; }
|
||||||
auto operator++() -> appender& { return *this; }
|
auto operator++() -> appender& { return *this; }
|
||||||
auto operator++(int) -> appender { return *this; }
|
auto operator++(int) -> appender { return *this; }
|
||||||
};
|
};
|
||||||
@ -1142,7 +1160,7 @@ constexpr auto has_const_formatter() -> bool {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using buffer_appender = conditional_t<std::is_same<T, char>::value, appender,
|
using buffer_appender = conditional_t<std::is_same<T, char>::value, appender,
|
||||||
std::back_insert_iterator<buffer<T>>>;
|
back_insert_iterator<buffer<T>>>;
|
||||||
|
|
||||||
// Maps an output iterator to a buffer.
|
// Maps an output iterator to a buffer.
|
||||||
template <typename T, typename OutputIt>
|
template <typename T, typename OutputIt>
|
||||||
@ -1151,7 +1169,7 @@ auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {
|
|||||||
}
|
}
|
||||||
template <typename T, typename Buf,
|
template <typename T, typename Buf,
|
||||||
FMT_ENABLE_IF(std::is_base_of<buffer<char>, Buf>::value)>
|
FMT_ENABLE_IF(std::is_base_of<buffer<char>, Buf>::value)>
|
||||||
auto get_buffer(std::back_insert_iterator<Buf> out) -> buffer<char>& {
|
auto get_buffer(back_insert_iterator<Buf> out) -> buffer<char>& {
|
||||||
return get_container(out);
|
return get_container(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1531,9 +1549,8 @@ auto copy_str(InputIt begin, InputIt end, appender out) -> appender {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
template <typename Char, typename InputIt>
|
template <typename Char, typename InputIt>
|
||||||
auto copy_str(InputIt begin, InputIt end,
|
auto copy_str(InputIt begin, InputIt end, back_insert_iterator<std::string> out)
|
||||||
std::back_insert_iterator<std::string> out)
|
-> back_insert_iterator<std::string> {
|
||||||
-> std::back_insert_iterator<std::string> {
|
|
||||||
get_container(out).append(begin, end);
|
get_container(out).append(begin, end);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -1567,7 +1584,7 @@ struct is_output_iterator<
|
|||||||
|
|
||||||
template <typename It> struct is_back_insert_iterator : std::false_type {};
|
template <typename It> struct is_back_insert_iterator : std::false_type {};
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
struct is_back_insert_iterator<std::back_insert_iterator<Container>>
|
struct is_back_insert_iterator<back_insert_iterator<Container>>
|
||||||
: std::true_type {};
|
: std::true_type {};
|
||||||
|
|
||||||
// A type-erased reference to an std::locale to avoid a heavy <locale> include.
|
// A type-erased reference to an std::locale to avoid a heavy <locale> include.
|
||||||
@ -2726,7 +2743,7 @@ void check_format_string(S format_str) {
|
|||||||
|
|
||||||
template <typename Char = char> struct vformat_args {
|
template <typename Char = char> struct vformat_args {
|
||||||
using type = basic_format_args<
|
using type = basic_format_args<
|
||||||
basic_format_context<std::back_insert_iterator<buffer<Char>>, Char>>;
|
basic_format_context<back_insert_iterator<buffer<Char>>, Char>>;
|
||||||
};
|
};
|
||||||
template <> struct vformat_args<char> {
|
template <> struct vformat_args<char> {
|
||||||
using type = format_args;
|
using type = format_args;
|
||||||
@ -2869,7 +2886,7 @@ auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt {
|
|||||||
**Example**::
|
**Example**::
|
||||||
|
|
||||||
auto out = std::vector<char>();
|
auto out = std::vector<char>();
|
||||||
fmt::format_to(std::back_inserter(out), "{}", 42);
|
fmt::format_to(fmt::back_inserter(out), "{}", 42);
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename OutputIt, typename... T,
|
template <typename OutputIt, typename... T,
|
||||||
|
@ -263,12 +263,16 @@ FMT_END_NAMESPACE
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <> struct iterator_traits<fmt::appender> {
|
||||||
struct iterator_traits<fmt::appender> {
|
|
||||||
using value_type = void;
|
using value_type = void;
|
||||||
using iterator_category = std::output_iterator_tag;
|
using iterator_category = std::output_iterator_tag;
|
||||||
};
|
};
|
||||||
}
|
template <typename Container>
|
||||||
|
struct iterator_traits<fmt::back_insert_iterator<Container>> {
|
||||||
|
using value_type = void;
|
||||||
|
using iterator_category = std::output_iterator_tag;
|
||||||
|
};
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -500,6 +504,18 @@ FMT_INLINE void assume(bool condition) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extracts a reference to the container from back_insert_iterator.
|
||||||
|
template <typename Container>
|
||||||
|
inline auto get_container(std::back_insert_iterator<Container> it)
|
||||||
|
-> Container& {
|
||||||
|
using base = std::back_insert_iterator<Container>;
|
||||||
|
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.
|
// An approximation of iterator_t for pre-C++20 systems.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using iterator_t = decltype(std::begin(std::declval<T&>()));
|
using iterator_t = decltype(std::begin(std::declval<T&>()));
|
||||||
|
@ -23,7 +23,7 @@ namespace detail {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
using is_exotic_char = bool_constant<!std::is_same<T, char>::value>;
|
using is_exotic_char = bool_constant<!std::is_same<T, char>::value>;
|
||||||
|
|
||||||
inline auto write_loc(std::back_insert_iterator<detail::buffer<wchar_t>> out,
|
inline auto write_loc(back_insert_iterator<detail::buffer<wchar_t>> out,
|
||||||
loc_value value, const format_specs<wchar_t>& specs,
|
loc_value value, const format_specs<wchar_t>& specs,
|
||||||
locale_ref loc) -> bool {
|
locale_ref loc) -> bool {
|
||||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||||
|
Reference in New Issue
Block a user