Implement fmt::format_to into std::vector<char> (#4211)

* Implement fmt::format_to into std::vector<char>

Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>

* Move get_container to the trait

Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>

---------

Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
This commit is contained in:
Vladislav Shchapov 2024-10-26 21:23:59 +05:00 committed by GitHub
parent 4daa3d591f
commit 168df9a064
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 4 deletions

View File

@ -1973,15 +1973,37 @@ template <typename T = char> class counting_buffer : public buffer<T> {
template <typename T> template <typename T>
struct is_back_insert_iterator<basic_appender<T>> : std::true_type {}; struct is_back_insert_iterator<basic_appender<T>> : std::true_type {};
template <typename OutputIt, typename InputIt, typename = void>
struct has_back_insert_iterator_container_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 {};
// An optimized version of std::copy with the output value type (T). // An optimized version of std::copy with the output value type (T).
template <typename T, typename InputIt, typename OutputIt, template <typename T, typename InputIt, typename OutputIt,
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value)> FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&&
has_back_insert_iterator_container_append<
OutputIt, InputIt>::value)>
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
-> OutputIt { -> OutputIt {
get_container(out).append(begin, end); get_container(out).append(begin, end);
return out; 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)>
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
-> OutputIt {
auto& c = get_container(out);
c.insert(c.end(), begin, end);
return out;
}
template <typename T, typename InputIt, typename OutputIt, template <typename T, typename InputIt, typename OutputIt,
FMT_ENABLE_IF(!is_back_insert_iterator<OutputIt>::value)> FMT_ENABLE_IF(!is_back_insert_iterator<OutputIt>::value)>
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {

View File

@ -8,6 +8,7 @@
#include "fmt/compile.h" #include "fmt/compile.h"
#include <type_traits> #include <type_traits>
#include <vector>
#include "fmt/chrono.h" #include "fmt/chrono.h"
#include "fmt/ranges.h" #include "fmt/ranges.h"
@ -229,10 +230,14 @@ TEST(compile_test, unknown_format_fallback) {
EXPECT_EQ(" 42 ", EXPECT_EQ(" 42 ",
fmt::format(FMT_COMPILE("{name:^4}"), fmt::arg("name", 42))); fmt::format(FMT_COMPILE("{name:^4}"), fmt::arg("name", 42)));
std::vector<char> v; std::vector<char> v1;
fmt::format_to(std::back_inserter(v), FMT_COMPILE("{name:^4}"), fmt::format_to(std::back_inserter(v1), FMT_COMPILE("{}"), 42);
EXPECT_EQ("42", fmt::string_view(v1.data(), v1.size()));
std::vector<char> v2;
fmt::format_to(std::back_inserter(v2), FMT_COMPILE("{name:^4}"),
fmt::arg("name", 42)); fmt::arg("name", 42));
EXPECT_EQ(" 42 ", fmt::string_view(v.data(), v.size())); EXPECT_EQ(" 42 ", fmt::string_view(v2.data(), v2.size()));
char buffer[4]; char buffer[4];
auto result = fmt::format_to_n(buffer, 4, FMT_COMPILE("{name:^5}"), auto result = fmt::format_to_n(buffer, 4, FMT_COMPILE("{name:^5}"),