diff --git a/include/fmt/base.h b/include/fmt/base.h index 70f18c23..bf9347e0 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1858,6 +1858,65 @@ class fixed_buffer_traits { } }; +template +struct has_back_insert_iterator_container_append : std::false_type {}; + +template +struct has_back_insert_iterator_container_append< + OutputIt, InputIt, + void_t()) + .append(std::declval(), + std::declval()))>> : std::true_type {}; + +template +struct has_back_insert_iterator_container_insert_at_end : std::false_type {}; + +template +struct has_back_insert_iterator_container_insert_at_end< + OutputIt, InputIt, + void_t()) + .insert(get_container(std::declval()).end(), + std::declval(), + std::declval()))>> : std::true_type {}; + +// An optimized version of std::copy with the output value type (T). +template ::value&& + has_back_insert_iterator_container_append< + OutputIt, InputIt>::value)> +FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { + get_container(out).append(begin, end); + return out; +} + +template ::value && + !has_back_insert_iterator_container_append< + OutputIt, InputIt>::value && + has_back_insert_iterator_container_insert_at_end< + OutputIt, InputIt>::value)> +FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { + auto& c = get_container(out); + c.insert(c.end(), begin, end); + return out; +} + +template ::value && + (has_back_insert_iterator_container_append< + OutputIt, InputIt>::value || + has_back_insert_iterator_container_insert_at_end< + OutputIt, InputIt>::value)))> +FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { + while (begin != end) *out++ = static_cast(*begin++); + return out; +} + +template +FMT_CONSTEXPR auto copy(basic_string_view s, OutputIt out) -> OutputIt { + return copy(s.begin(), s.end(), out); +} + // A buffer that writes to an output iterator when flushed. template class iterator_buffer : public Traits, public buffer { @@ -1875,7 +1934,12 @@ class iterator_buffer : public Traits, public buffer { this->clear(); const T* begin = data_; const T* end = begin + this->limit(size); - while (begin != end) *out_++ = *begin++; +#if defined(__cpp_if_constexpr) + if constexpr (std::is_move_assignable::value) + out_ = copy(begin, end, out_); + else +#endif + while (begin != end) *out_++ = *begin++; } public: diff --git a/include/fmt/format.h b/include/fmt/format.h index b358f042..b9df2526 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -548,65 +548,6 @@ FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { return out + count; } -template -struct has_back_insert_iterator_container_append : std::false_type {}; - -template -struct has_back_insert_iterator_container_append< - OutputIt, InputIt, - void_t()) - .append(std::declval(), - std::declval()))>> : std::true_type {}; - -template -struct has_back_insert_iterator_container_insert_at_end : std::false_type {}; - -template -struct has_back_insert_iterator_container_insert_at_end< - OutputIt, InputIt, - void_t()) - .insert(get_container(std::declval()).end(), - std::declval(), - std::declval()))>> : std::true_type {}; - -// An optimized version of std::copy with the output value type (T). -template ::value&& - has_back_insert_iterator_container_append< - OutputIt, InputIt>::value)> -FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { - get_container(out).append(begin, end); - return out; -} - -template ::value && - !has_back_insert_iterator_container_append< - OutputIt, InputIt>::value && - has_back_insert_iterator_container_insert_at_end< - OutputIt, InputIt>::value)> -FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { - auto& c = get_container(out); - c.insert(c.end(), begin, end); - return out; -} - -template ::value && - (has_back_insert_iterator_container_append< - OutputIt, InputIt>::value || - has_back_insert_iterator_container_insert_at_end< - OutputIt, InputIt>::value)))> -FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { - while (begin != end) *out++ = static_cast(*begin++); - return out; -} - -template -FMT_CONSTEXPR auto copy(basic_string_view s, OutputIt out) -> OutputIt { - return copy(s.begin(), s.end(), out); -} - template FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end, OutputIt out) -> OutputIt {