Make join() handle non-const-only begin/end ranges (#1786)
See fmtlib/fmt#1784. Add tests that demonstrate the problem and check obvious variations.
This commit is contained in:
parent
d69e2da221
commit
febffa4e64
@ -3420,15 +3420,14 @@ arg_join<It, Sentinel, wchar_t> join(It begin, Sentinel end, wstring_view sep) {
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
arg_join<detail::iterator_t<const Range>, detail::sentinel_t<const Range>, char>
|
arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, char> join(
|
||||||
join(const Range& range, string_view sep) {
|
Range&& range, string_view sep) {
|
||||||
return join(std::begin(range), std::end(range), sep);
|
return join(std::begin(range), std::end(range), sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
arg_join<detail::iterator_t<const Range>, detail::sentinel_t<const Range>,
|
arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, wchar_t> join(
|
||||||
wchar_t>
|
Range&& range, wstring_view sep) {
|
||||||
join(const Range& range, wstring_view sep) {
|
|
||||||
return join(std::begin(range), std::end(range), sep);
|
return join(std::begin(range), std::end(range), sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,3 +153,37 @@ TEST(RangesTest, JoinSentinel) {
|
|||||||
EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello));
|
EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello));
|
||||||
EXPECT_EQ("h_e_l_l_o", fmt::format("{}", fmt::join(hello, "_")));
|
EXPECT_EQ("h_e_l_l_o", fmt::format("{}", fmt::join(hello, "_")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A range that provides non-const only begin()/end() to test fmt::join handles
|
||||||
|
// that
|
||||||
|
//
|
||||||
|
// Some ranges (eg those produced by range-v3's views::filter()) can cache
|
||||||
|
// information during iteration so they only provide non-const begin()/end().
|
||||||
|
template <typename T> class non_const_only_range {
|
||||||
|
private:
|
||||||
|
std::vector<T> vec;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using const_iterator = typename ::std::vector<T>::const_iterator;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
explicit non_const_only_range(Args&&... args)
|
||||||
|
: vec(::std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
|
const_iterator begin() { return vec.begin(); }
|
||||||
|
const_iterator end() { return vec.end(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(RangesTest, JoinRange) {
|
||||||
|
non_const_only_range<int> x(3, 0);
|
||||||
|
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(x, ",")));
|
||||||
|
EXPECT_EQ("0,0,0",
|
||||||
|
fmt::format("{}", fmt::join(non_const_only_range<int>(3, 0), ",")));
|
||||||
|
|
||||||
|
std::vector<int> y(3, 0);
|
||||||
|
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(y, ",")));
|
||||||
|
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(std::vector<int>(3, 0), ",")));
|
||||||
|
|
||||||
|
const std::vector<int> z(3, 0);
|
||||||
|
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ",")));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user