diff --git a/include/fmt/format.h b/include/fmt/format.h index c24d5ba0..93cff852 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2748,7 +2748,12 @@ using arg_join FMT_DEPRECATED_ALIAS = join_view; template struct formatter, Char> { private: - using value_type = typename std::iterator_traits::value_type; + using value_type = + #ifdef __cpp_lib_ranges + std::iter_value_t; + #else + typename std::iterator_traits::value_type; + #endif using context = buffer_context; using mapper = detail::arg_mapper; @@ -2782,11 +2787,13 @@ struct formatter, Char> { auto it = value.begin; auto out = ctx.out(); if (it != value.end) { - out = value_formatter_.format(map(*it++), ctx); + out = value_formatter_.format(map(*it), ctx); + ++it; while (it != value.end) { out = detail::copy_str(value.sep.begin(), value.sep.end(), out); ctx.advance_to(out); - out = value_formatter_.format(map(*it++), ctx); + out = value_formatter_.format(map(*it), ctx); + ++it; } } return out; diff --git a/test/ranges-test.cc b/test/ranges-test.cc index 1c572e62..a6aea992 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -258,6 +258,33 @@ struct zstring { zstring_sentinel end() const { return {}; } }; +#ifdef __cpp_lib_ranges +struct cpp20_only_range { + struct iterator { + int i = 0; + + using value_type = int; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::input_iterator_tag; + + iterator() = default; + iterator(int i) : i(i) { } + int operator*() const { return i; } + iterator& operator++() { ++i; return *this; } + void operator++(int) { ++*this; } + bool operator==(const iterator& rhs) const { return i == rhs.i; } + }; + + int lo; + int hi; + + iterator begin() const { return iterator(lo); } + iterator end() const { return iterator(hi); } +}; + +static_assert(std::input_iterator); +#endif + TEST(ranges_test, join_sentinel) { auto hello = zstring{"hello"}; EXPECT_EQ(fmt::format("{}", hello), "['h', 'e', 'l', 'l', 'o']"); @@ -282,6 +309,11 @@ TEST(ranges_test, join_range) { const auto z = std::vector(3u, 0); EXPECT_EQ(fmt::format("{}", fmt::join(z, ",")), "0,0,0"); + + #ifdef __cpp_lib_ranges + EXPECT_EQ(fmt::format("{}", cpp20_only_range{.lo=0, .hi=5}), "[0, 1, 2, 3, 4]"); + EXPECT_EQ(fmt::format("{}", fmt::join(cpp20_only_range{.lo=0, .hi=5}, ",")), "0,1,2,3,4"); + #endif } #endif // FMT_RANGES_TEST_ENABLE_JOIN