diff --git a/include/fmt/base.h b/include/fmt/base.h index bf9347e0..3c629859 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1859,42 +1859,38 @@ class fixed_buffer_traits { }; template -struct has_back_insert_iterator_container_append : std::false_type {}; +struct has_append : std::false_type {}; template -struct has_back_insert_iterator_container_append< - OutputIt, InputIt, - void_t()) - .append(std::declval(), - std::declval()))>> : std::true_type {}; +struct has_append()) + .append(std::declval(), + std::declval()))>> + : std::true_type {}; -template -struct has_back_insert_iterator_container_insert_at_end : std::false_type {}; +template +struct has_insert : 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 {}; +template +struct has_insert()) + .insert({}, 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_ENABLE_IF(is_back_insert_iterator() && + has_append())> 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_ENABLE_IF(is_back_insert_iterator() && + !has_append() && + has_insert())> 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 ::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() || + !(has_append() || + has_insert()))> 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 { @@ -1934,12 +1923,7 @@ class iterator_buffer : public Traits, public buffer { this->clear(); const T* begin = data_; const T* end = begin + this->limit(size); -#if defined(__cpp_if_constexpr) - if constexpr (std::is_move_assignable::value) - out_ = copy(begin, end, out_); - else -#endif - while (begin != end) *out_++ = *begin++; + out_ = copy(begin, end, out_); } public: diff --git a/include/fmt/format.h b/include/fmt/format.h index b9df2526..e46b613e 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -548,6 +548,11 @@ FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { return out + count; } +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 { diff --git a/test/base-test.cc b/test/base-test.cc index bf268875..9575e055 100644 --- a/test/base-test.cc +++ b/test/base-test.cc @@ -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&) { }