Skip to content

Commit f711b96

Browse files
committed
update fmt::join to support more character types
1 parent 8d3f731 commit f711b96

File tree

4 files changed

+37
-23
lines changed

4 files changed

+37
-23
lines changed

include/fmt/base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1820,7 +1820,7 @@ template <typename T> class buffer {
18201820
}
18211821
// A loop is faster than memcpy on small sizes.
18221822
T* out = ptr_ + size;
1823-
for (size_t i = 0; i < count; ++i) out[i] = begin[i];
1823+
for (size_t i = 0; i < count; ++i) out[i] = static_cast<T>(begin[i]);
18241824
size_ += count;
18251825
begin += count;
18261826
}

include/fmt/format.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,8 +1097,8 @@ inline auto digits2_i(size_t value) noexcept -> const char* {
10971097
}
10981098

10991099
template <typename Char> constexpr auto getsign(sign s) -> Char {
1100-
return static_cast<char>(((' ' << 24) | ('+' << 16) | ('-' << 8)) >>
1101-
(static_cast<int>(s) * 8));
1100+
return static_cast<Char>(static_cast<char>(((' ' << 24) | ('+' << 16) | ('-' << 8)) >>
1101+
(static_cast<int>(s) * 8)));
11021102
}
11031103

11041104
template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
@@ -3621,8 +3621,8 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
36213621
memcpy(ptr, prefix, 2);
36223622
ptr += 2;
36233623
} else {
3624-
*ptr++ = prefix[0];
3625-
*ptr++ = prefix[1];
3624+
*ptr++ = static_cast<Char>(prefix[0]);
3625+
*ptr++ = static_cast<Char>(prefix[1]);
36263626
}
36273627
if (abs_exponent >= 100) {
36283628
*ptr++ = static_cast<Char>('0' + abs_exponent / 100);

include/fmt/xchar.h

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -141,29 +141,29 @@ auto arg(const wchar_t* name, const T& arg) -> detail::named_arg<T, wchar_t> {
141141
return {name, arg};
142142
}
143143

144-
template <typename It, typename Sentinel>
145-
auto join(It begin, Sentinel end, wstring_view sep)
146-
-> join_view<It, Sentinel, wchar_t> {
147-
return {begin, end, sep};
144+
template <typename It, typename Sentinel, typename S>
145+
auto join(It begin, Sentinel end, S &&sep)
146+
-> join_view<It, Sentinel, typename decltype(detail::to_string_view(std::declval<S>()))::value_type> {
147+
return {begin, end, detail::to_string_view(sep)};
148148
}
149149

150-
template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
151-
auto join(Range&& range, wstring_view sep)
150+
template <typename Range, typename S, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
151+
auto join(Range &&range, S &&sep)
152152
-> join_view<decltype(std::begin(range)), decltype(std::end(range)),
153-
wchar_t> {
154-
return join(std::begin(range), std::end(range), sep);
153+
typename decltype(detail::to_string_view(std::declval<S>()))::value_type> {
154+
return {std::begin(range), std::end(range), detail::to_string_view(sep)};
155155
}
156156

157-
template <typename T>
158-
auto join(std::initializer_list<T> list, wstring_view sep)
159-
-> join_view<const T*, const T*, wchar_t> {
160-
return join(std::begin(list), std::end(list), sep);
157+
template <typename T, typename S>
158+
auto join(std::initializer_list<T> list, S &&sep)
159+
-> join_view<const T *, const T *, typename decltype(detail::to_string_view(std::declval<S>()))::value_type> {
160+
return {std::begin(list), std::end(list), detail::to_string_view(sep)};
161161
}
162162

163-
template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
164-
auto join(const Tuple& tuple, basic_string_view<wchar_t> sep)
165-
-> tuple_join_view<Tuple, wchar_t> {
166-
return {tuple, sep};
163+
template <typename Tuple, typename S, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
164+
auto join(const Tuple &tuple, S &&sep)
165+
-> tuple_join_view<Tuple, typename decltype(detail::to_string_view(std::declval<S>()))::value_type> {
166+
return {tuple, detail::to_string_view(sep)};
167167
}
168168

169169
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>

test/xchar-test.cc

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,23 @@ TEST(xchar_test, print) {
167167

168168
TEST(xchar_test, join) {
169169
int v[3] = {1, 2, 3};
170+
EXPECT_EQ(fmt::format(u"({})", fmt::join(v, v + 3, u", ")), u"(1, 2, 3)");
171+
EXPECT_EQ(fmt::format(U"({})", fmt::join(v, v + 3, U", ")), U"(1, 2, 3)");
170172
EXPECT_EQ(fmt::format(L"({})", fmt::join(v, v + 3, L", ")), L"(1, 2, 3)");
171-
auto t = std::tuple<wchar_t, int, float>('a', 1, 2.0f);
172-
EXPECT_EQ(fmt::format(L"({})", fmt::join(t, L", ")), L"(a, 1, 2)");
173+
auto vector = std::vector<int>{1, 2, 3};
174+
EXPECT_EQ(fmt::format(u"({})", fmt::join(vector, u", ")), u"(1, 2, 3)");
175+
EXPECT_EQ(fmt::format(U"({})", fmt::join(vector, U", ")), U"(1, 2, 3)");
176+
EXPECT_EQ(fmt::format(L"({})", fmt::join(vector, L", ")), L"(1, 2, 3)");
177+
auto initializer_list = {1, 2, 3};
178+
EXPECT_EQ(fmt::format(u"({})", fmt::join(initializer_list, u", ")), u"(1, 2, 3)");
179+
EXPECT_EQ(fmt::format(U"({})", fmt::join(initializer_list, U", ")), U"(1, 2, 3)");
180+
EXPECT_EQ(fmt::format(L"({})", fmt::join(initializer_list, L", ")), L"(1, 2, 3)");
181+
auto tuple_char16 = std::tuple<char16_t, int, float>(u'a', 1, 2.0f);
182+
EXPECT_EQ(fmt::format(u"({})", fmt::join(tuple_char16, u", ")), u"(a, 1, 2)");
183+
auto tuple_char32 = std::tuple<char32_t, int, float>(U'a', 1, 2.0f);
184+
EXPECT_EQ(fmt::format(U"({})", fmt::join(tuple_char32, U", ")), U"(a, 1, 2)");
185+
auto tuple_wchar = std::tuple<wchar_t, int, float>(L'a', 1, 2.0f);
186+
EXPECT_EQ(fmt::format(L"({})", fmt::join(tuple_wchar, L", ")), L"(a, 1, 2)");
173187
}
174188

175189
#ifdef __cpp_lib_byte

0 commit comments

Comments
 (0)