Skip to content

Commit 7b2c4d0

Browse files
authored
Speed up iterator_buffer (#4679)
1 parent dc05bee commit 7b2c4d0

2 files changed

Lines changed: 65 additions & 60 deletions

File tree

include/fmt/base.h

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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.
18621921
template <typename OutputIt, typename T, typename Traits = buffer_traits>
18631922
class 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:

include/fmt/format.h

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -548,65 +548,6 @@ FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
548548
return out + count;
549549
}
550550

551-
template <typename OutputIt, typename InputIt, typename = void>
552-
struct has_back_insert_iterator_container_append : std::false_type {};
553-
554-
template <typename OutputIt, typename InputIt>
555-
struct has_back_insert_iterator_container_append<
556-
OutputIt, InputIt,
557-
void_t<decltype(get_container(std::declval<OutputIt>())
558-
.append(std::declval<InputIt>(),
559-
std::declval<InputIt>()))>> : std::true_type {};
560-
561-
template <typename OutputIt, typename InputIt, typename = void>
562-
struct has_back_insert_iterator_container_insert_at_end : std::false_type {};
563-
564-
template <typename OutputIt, typename InputIt>
565-
struct has_back_insert_iterator_container_insert_at_end<
566-
OutputIt, InputIt,
567-
void_t<decltype(get_container(std::declval<OutputIt>())
568-
.insert(get_container(std::declval<OutputIt>()).end(),
569-
std::declval<InputIt>(),
570-
std::declval<InputIt>()))>> : std::true_type {};
571-
572-
// An optimized version of std::copy with the output value type (T).
573-
template <typename T, typename InputIt, typename OutputIt,
574-
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&&
575-
has_back_insert_iterator_container_append<
576-
OutputIt, InputIt>::value)>
577-
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
578-
get_container(out).append(begin, end);
579-
return out;
580-
}
581-
582-
template <typename T, typename InputIt, typename OutputIt,
583-
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value &&
584-
!has_back_insert_iterator_container_append<
585-
OutputIt, InputIt>::value &&
586-
has_back_insert_iterator_container_insert_at_end<
587-
OutputIt, InputIt>::value)>
588-
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
589-
auto& c = get_container(out);
590-
c.insert(c.end(), begin, end);
591-
return out;
592-
}
593-
594-
template <typename T, typename InputIt, typename OutputIt,
595-
FMT_ENABLE_IF(!(is_back_insert_iterator<OutputIt>::value &&
596-
(has_back_insert_iterator_container_append<
597-
OutputIt, InputIt>::value ||
598-
has_back_insert_iterator_container_insert_at_end<
599-
OutputIt, InputIt>::value)))>
600-
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
601-
while (begin != end) *out++ = static_cast<T>(*begin++);
602-
return out;
603-
}
604-
605-
template <typename T, typename V, typename OutputIt>
606-
FMT_CONSTEXPR auto copy(basic_string_view<V> s, OutputIt out) -> OutputIt {
607-
return copy<T>(s.begin(), s.end(), out);
608-
}
609-
610551
template <typename OutChar, typename InputIt, typename OutputIt>
611552
FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end,
612553
OutputIt out) -> OutputIt {

0 commit comments

Comments
 (0)