@@ -1858,6 +1858,65 @@ class fixed_buffer_traits {
18581858 }
18591859};
18601860
1861+ template <typename OutputIt, typename InputIt, typename = void >
1862+ struct has_back_insert_iterator_container_append : std::false_type {};
1863+
1864+ template <typename OutputIt, typename InputIt>
1865+ struct has_back_insert_iterator_container_append <
1866+ OutputIt, InputIt,
1867+ void_t <decltype (get_container(std::declval<OutputIt>())
1868+ .append(std::declval<InputIt>(),
1869+ std::declval<InputIt>()))>> : std::true_type {};
1870+
1871+ template <typename OutputIt, typename InputIt, typename = void >
1872+ struct has_back_insert_iterator_container_insert_at_end : std::false_type {};
1873+
1874+ template <typename OutputIt, typename InputIt>
1875+ struct has_back_insert_iterator_container_insert_at_end <
1876+ OutputIt, InputIt,
1877+ void_t <decltype (get_container(std::declval<OutputIt>())
1878+ .insert(get_container(std::declval<OutputIt>()).end(),
1879+ std::declval<InputIt>(),
1880+ std::declval<InputIt>()))>> : std::true_type {};
1881+
1882+ // An optimized version of std::copy with the output value type (T).
1883+ template <typename T, typename InputIt, typename OutputIt,
1884+ FMT_ENABLE_IF (is_back_insert_iterator<OutputIt>::value&&
1885+ has_back_insert_iterator_container_append<
1886+ OutputIt, InputIt>::value)>
1887+ FMT_CONSTEXPR auto copy (InputIt begin, InputIt end, OutputIt out) -> OutputIt {
1888+ get_container (out).append (begin, end);
1889+ return out;
1890+ }
1891+
1892+ template <typename T, typename InputIt, typename OutputIt,
1893+ FMT_ENABLE_IF (is_back_insert_iterator<OutputIt>::value &&
1894+ !has_back_insert_iterator_container_append<
1895+ OutputIt, InputIt>::value &&
1896+ has_back_insert_iterator_container_insert_at_end<
1897+ OutputIt, InputIt>::value)>
1898+ FMT_CONSTEXPR auto copy (InputIt begin, InputIt end, OutputIt out) -> OutputIt {
1899+ auto & c = get_container (out);
1900+ c.insert (c.end (), begin, end);
1901+ return out;
1902+ }
1903+
1904+ template <typename T, typename InputIt, typename OutputIt,
1905+ FMT_ENABLE_IF (!(is_back_insert_iterator<OutputIt>::value &&
1906+ (has_back_insert_iterator_container_append<
1907+ OutputIt, InputIt>::value ||
1908+ has_back_insert_iterator_container_insert_at_end<
1909+ OutputIt, InputIt>::value)))>
1910+ FMT_CONSTEXPR auto copy (InputIt begin, InputIt end, OutputIt out) -> OutputIt {
1911+ while (begin != end) *out++ = static_cast <T>(*begin++);
1912+ return out;
1913+ }
1914+
1915+ template <typename T, typename V, typename OutputIt>
1916+ FMT_CONSTEXPR auto copy (basic_string_view<V> s, OutputIt out) -> OutputIt {
1917+ return copy<T>(s.begin (), s.end (), out);
1918+ }
1919+
18611920// A buffer that writes to an output iterator when flushed.
18621921template <typename OutputIt, typename T, typename Traits = buffer_traits>
18631922class iterator_buffer : public Traits , public buffer <T> {
@@ -1875,7 +1934,12 @@ class iterator_buffer : public Traits, public buffer<T> {
18751934 this ->clear ();
18761935 const T* begin = data_;
18771936 const T* end = begin + this ->limit (size);
1878- while (begin != end) *out_++ = *begin++;
1937+ #if defined(__cpp_if_constexpr)
1938+ if constexpr (std::is_move_assignable<OutputIt>::value)
1939+ out_ = copy<T>(begin, end, out_);
1940+ else
1941+ #endif
1942+ while (begin != end) *out_++ = *begin++;
18791943 }
18801944
18811945 public:
0 commit comments