Simplify copy

This commit is contained in:
Victor Zverovich 2026-03-28 09:33:45 -07:00
parent 7b2c4d064b
commit 602df7dab8
3 changed files with 31 additions and 42 deletions

View File

@ -1859,42 +1859,38 @@ class fixed_buffer_traits {
};
template <typename OutputIt, typename InputIt, typename = void>
struct has_back_insert_iterator_container_append : std::false_type {};
struct has_append : std::false_type {};
template <typename OutputIt, typename InputIt>
struct has_back_insert_iterator_container_append<
OutputIt, InputIt,
void_t<decltype(get_container(std::declval<OutputIt>())
.append(std::declval<InputIt>(),
std::declval<InputIt>()))>> : std::true_type {};
struct has_append<OutputIt, InputIt,
void_t<decltype(get_container(std::declval<OutputIt>())
.append(std::declval<InputIt>(),
std::declval<InputIt>()))>>
: std::true_type {};
template <typename OutputIt, typename InputIt, typename = void>
struct has_back_insert_iterator_container_insert_at_end : std::false_type {};
template <typename OutputIt, typename T, typename = void>
struct has_insert : std::false_type {};
template <typename OutputIt, typename InputIt>
struct has_back_insert_iterator_container_insert_at_end<
OutputIt, InputIt,
void_t<decltype(get_container(std::declval<OutputIt>())
.insert(get_container(std::declval<OutputIt>()).end(),
std::declval<InputIt>(),
std::declval<InputIt>()))>> : std::true_type {};
template <typename OutputIt, typename T>
struct has_insert<OutputIt, T,
void_t<decltype(get_container(std::declval<OutputIt>())
.insert({}, std::declval<T>(),
std::declval<T>()))>>
: std::true_type {};
// An optimized version of std::copy with the output value type (T).
template <typename T, typename InputIt, typename OutputIt,
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&&
has_back_insert_iterator_container_append<
OutputIt, InputIt>::value)>
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>() &&
has_append<OutputIt, InputIt>())>
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
get_container(out).append(begin, end);
return out;
}
template <typename T, typename InputIt, typename OutputIt,
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value &&
!has_back_insert_iterator_container_append<
OutputIt, InputIt>::value &&
has_back_insert_iterator_container_insert_at_end<
OutputIt, InputIt>::value)>
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>() &&
!has_append<OutputIt, InputIt>() &&
has_insert<OutputIt, InputIt>())>
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
auto& c = get_container(out);
c.insert(c.end(), begin, end);
@ -1902,21 +1898,14 @@ FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
}
template <typename T, typename InputIt, typename OutputIt,
FMT_ENABLE_IF(!(is_back_insert_iterator<OutputIt>::value &&
(has_back_insert_iterator_container_append<
OutputIt, InputIt>::value ||
has_back_insert_iterator_container_insert_at_end<
OutputIt, InputIt>::value)))>
FMT_ENABLE_IF(!is_back_insert_iterator<OutputIt>() ||
!(has_append<OutputIt, InputIt>() ||
has_insert<OutputIt, InputIt>()))>
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
while (begin != end) *out++ = static_cast<T>(*begin++);
return out;
}
template <typename T, typename V, typename OutputIt>
FMT_CONSTEXPR auto copy(basic_string_view<V> s, OutputIt out) -> OutputIt {
return copy<T>(s.begin(), s.end(), out);
}
// A buffer that writes to an output iterator when flushed.
template <typename OutputIt, typename T, typename Traits = buffer_traits>
class iterator_buffer : public Traits, public buffer<T> {
@ -1934,12 +1923,7 @@ class iterator_buffer : public Traits, public buffer<T> {
this->clear();
const T* begin = data_;
const T* end = begin + this->limit(size);
#if defined(__cpp_if_constexpr)
if constexpr (std::is_move_assignable<OutputIt>::value)
out_ = copy<T>(begin, end, out_);
else
#endif
while (begin != end) *out_++ = *begin++;
out_ = copy<T>(begin, end, out_);
}
public:

View File

@ -548,6 +548,11 @@ FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
return out + count;
}
template <typename T, typename V, typename OutputIt>
FMT_CONSTEXPR auto copy(basic_string_view<V> s, OutputIt out) -> OutputIt {
return copy<T>(s.begin(), s.end(), out);
}
template <typename OutChar, typename InputIt, typename OutputIt>
FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end,
OutputIt out) -> OutputIt {

View File

@ -811,10 +811,10 @@ TEST(base_test, throw_in_buffer_dtor) {
constexpr int buffer_size = 256;
struct throwing_iterator {
int& count;
int* count;
auto operator=(char) -> throwing_iterator& {
if (++count > buffer_size) throw std::exception();
if (++*count > buffer_size) throw std::exception();
return *this;
}
auto operator*() -> throwing_iterator& { return *this; }
@ -824,7 +824,7 @@ TEST(base_test, throw_in_buffer_dtor) {
try {
int count = 0;
fmt::format_to(throwing_iterator{count}, fmt::runtime("{:{}}{"), "",
fmt::format_to(throwing_iterator{&count}, fmt::runtime("{:{}}{"), "",
buffer_size + 1);
} catch (const std::exception&) {
}