[libc++][test] Refactor SmallBasicString uses in range.lazy.split tests

The tests for `std::ranges::lazy_split_view` heavily use a wrapper class around
`std::string` because `std::string` was not `constexpr` until recently. Where
possible, remove the wrapper class and extra functionality no longer needed.
Remove `libcxx/test/std/ranges/range.adaptors/range.lazy.split/small_string.h`
and inline its one use remaining in
`libcxx/test/std/ranges/range.adaptors/range.lazy.split/general.pass.cpp`.

Differential Revision: https://reviews.llvm.org/D126663
This commit is contained in:
Joe Loser 2022-05-28 19:08:25 -06:00
parent 11f75e0a2d
commit ae2ae84ffe
No known key found for this signature in database
GPG Key ID: 1CDBEBC050EA230D
7 changed files with 75 additions and 132 deletions

View File

@ -16,13 +16,8 @@
#include <cassert>
#include <string_view>
#include <utility>
#include "small_string.h"
#include "types.h"
constexpr bool operator==(const InputView& lhs, const InputView& rhs) {
return SmallString(lhs) == SmallString(rhs);
}
constexpr bool test() {
// Can copy `lazy_split_view`.
{

View File

@ -17,10 +17,10 @@
#include <ranges>
#include <cassert>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include "small_string.h"
#include "types.h"
struct ElementWithCounting {
@ -72,24 +72,15 @@ struct RangeWithCounting {
static_assert( std::ranges::forward_range<RangeWithCounting>);
static_assert(!std::ranges::view<RangeWithCounting>);
struct StrRange {
SmallString buffer_;
constexpr explicit StrRange() = default;
constexpr StrRange(const char* ptr) : buffer_(ptr) {}
constexpr const char* begin() const { return buffer_.begin(); }
constexpr const char* end() const { return buffer_.end(); }
constexpr bool operator==(const StrRange& rhs) const { return buffer_ == rhs.buffer_; }
};
static_assert( std::ranges::random_access_range<StrRange>);
static_assert(!std::ranges::view<StrRange>);
static_assert( std::is_copy_constructible_v<StrRange>);
struct StrView : std::ranges::view_base {
SmallString buffer_;
std::string_view buffer_;
constexpr explicit StrView() = default;
constexpr StrView(const char* ptr) : buffer_(ptr) {}
// Intentionally don't forward to range constructor for std::string_view since
// this test needs to work on C++20 as well and the range constructor is only for
// C++23 and later.
template <std::ranges::range R>
constexpr StrView(R&& r) : buffer_(std::forward<R>(r)) {}
constexpr StrView(R&& r) : buffer_(r.begin(), r.end()) {}
constexpr const char* begin() const { return buffer_.begin(); }
constexpr const char* end() const { return buffer_.end(); }
constexpr bool operator==(const StrView& rhs) const { return buffer_ == rhs.buffer_; }
@ -102,9 +93,9 @@ constexpr bool test() {
{
using V = std::ranges::lazy_split_view<StrView, StrView>;
// Calling the constructor with `(StrRange, range_value_t)`.
// Calling the constructor with `(std::string, range_value_t)`.
{
StrRange input;
std::string input;
V v(input, ' ');
assert(v.base() == input);
}

View File

@ -25,9 +25,33 @@
#include <string_view>
#include <utility>
#include <vector>
#include "small_string.h"
#include "types.h"
// A constexpr-friendly lightweight string, primarily useful for comparisons.
// Unlike `std::string_view`, it copies the given string into an
// internal buffer and can work with non-contiguous inputs.
template <class Char>
class BasicSmallString {
std::basic_string<Char> buffer_{};
public:
constexpr BasicSmallString(std::basic_string_view<Char> v) : buffer_(v) {}
template <class I, class S>
constexpr BasicSmallString(I b, const S& e) {
for (; b != e; ++b) {
buffer_ += *b;
}
}
template <std::ranges::range R>
constexpr BasicSmallString(R&& from) : BasicSmallString(from.begin(), from.end()) {}
friend constexpr bool operator==(const BasicSmallString& lhs, const BasicSmallString& rhs) {
return lhs.buffer_ == rhs.buffer_;
}
};
template <std::ranges::view View, std::ranges::range Expected>
constexpr bool is_equal(View& view, const Expected& expected) {
using Char = std::ranges::range_value_t<std::ranges::range_value_t<View>>;
@ -55,7 +79,7 @@ constexpr bool test_with_piping(T&& input, Separator&& separator, std::array<U,
for (auto e : input | std::ranges::views::lazy_split(separator)) {
if (expected_it == expected.end())
return false;
if (SmallString(e) != *expected_it)
if (!std::ranges::equal(e, *expected_it))
return false;
++expected_it;

View File

@ -13,14 +13,16 @@
#include <ranges>
#include <algorithm>
#include <cassert>
#include <string>
#include <string_view>
#include <type_traits>
#include "../small_string.h"
#include "../types.h"
template <class View, class Separator>
constexpr void test_one(Separator sep) {
using namespace std::string_literals;
using namespace std::string_view_literals;
View v("abc def ghi"sv, sep);
@ -29,16 +31,16 @@ constexpr void test_one(Separator sep) {
{
auto i = v.begin();
static_assert(!std::is_reference_v<decltype(*i)>);
assert(SmallString(*i) == "abc"_str);
assert(SmallString(*(++i)) == "def"_str);
assert(SmallString(*(++i)) == "ghi"_str);
assert(std::ranges::equal(*i, "abc"s));
assert(std::ranges::equal(*(++i), "def"s));
assert(std::ranges::equal(*(++i), "ghi"s));
}
// Const iterator.
{
const auto ci = v.begin();
static_assert(!std::is_reference_v<decltype(*ci)>);
assert(SmallString(*ci) == "abc"_str);
assert(std::ranges::equal(*ci, "abc"s));
}
}

View File

@ -17,11 +17,12 @@
#include <ranges>
#include <algorithm>
#include <string_view>
#include "../small_string.h"
#include <cassert>
#include <string>
#include "../types.h"
constexpr bool test() {
using namespace std::string_literals;
// Can call `outer-iterator::operator++`; `View` is a forward range.
{
SplitViewForward v("abc def ghi", " ");
@ -29,23 +30,23 @@ constexpr bool test() {
// ++i
{
auto i = v.begin();
assert(*i == "abc"_str);
assert(std::ranges::equal(*i, "abc"s));
decltype(auto) i2 = ++i;
static_assert(std::is_lvalue_reference_v<decltype(i2)>);
assert(&i2 == &i);
assert(*i2 == "def"_str);
assert(std::ranges::equal(*i2, "def"s));
}
// i++
{
auto i = v.begin();
assert(*i == "abc"_str);
assert(std::ranges::equal(*i, "abc"s));
decltype(auto) i2 = i++;
static_assert(!std::is_reference_v<decltype(i2)>);
assert(*i2 == "abc"_str);
assert(*i == "def"_str);
assert(std::ranges::equal(*i2, "abc"s));
assert(std::ranges::equal(*i, "def"s));
}
}
@ -56,22 +57,22 @@ constexpr bool test() {
// ++i
{
auto i = v.begin();
assert(*i == "abc"_str);
assert(std::ranges::equal(*i, "abc"s));
decltype(auto) i2 = ++i;
static_assert(std::is_lvalue_reference_v<decltype(i2)>);
assert(&i2 == &i);
assert(*i2 == "def"_str);
assert(std::ranges::equal(*i2, "def"s));
}
// i++
{
auto i = v.begin();
assert(*i == "abc"_str);
assert(std::ranges::equal(*i, "abc"s));
static_assert(std::is_void_v<decltype(i++)>);
i++;
assert(*i == "def"_str);
assert(std::ranges::equal(*i, "def"s));
}
}

View File

@ -1,79 +0,0 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_SMALL_STRING_H
#define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_SMALL_STRING_H
#include <algorithm>
#include <cassert>
#include <ranges>
#include <string_view>
// A constexpr-friendly lightweight string, primarily useful for comparisons.
// Unlike `std::string`, all functions are `constexpr`. Unlike `std::string_view`, it copies the given string into an
// internal buffer and can work with non-contiguous inputs.
//
// TODO(var-const): remove once https://reviews.llvm.org/D110598 lands and `std::string` can be used instead of this
// class.
template <class Char>
class BasicSmallString {
constexpr static int N = 32;
Char buffer_[N] = {};
size_t size_ = 0;
public:
// Main constructors.
constexpr BasicSmallString() = default;
constexpr BasicSmallString(std::basic_string_view<Char> v) : size_(v.size()) {
assert(size_ < N);
if (size_ == 0) return;
std::copy(v.begin(), v.end(), buffer_);
}
template <class I, class S>
constexpr BasicSmallString(I b, const S& e) {
for (; b != e; ++b) {
buffer_[size_++] = *b;
assert(size_ < N);
}
}
// Delegating constructors.
constexpr BasicSmallString(const Char* ptr, size_t size) : BasicSmallString(std::basic_string_view<Char>(ptr, size)) {
}
template <std::ranges::range R>
constexpr BasicSmallString(R&& from) : BasicSmallString(from.begin(), from.end()) {
}
// Iterators.
constexpr Char* begin() { return buffer_; }
constexpr Char* end() { return buffer_ + size_; }
constexpr const Char* begin() const { return buffer_; }
constexpr const Char* end() const { return buffer_ + size_; }
friend constexpr bool operator==(const BasicSmallString& lhs, const BasicSmallString& rhs) {
return lhs.size_ == rhs.size_ && std::equal(lhs.buffer_, lhs.buffer_ + lhs.size_, rhs.buffer_);
}
friend constexpr bool operator==(const BasicSmallString& lhs, std::string_view rhs) {
return lhs == BasicSmallString(rhs);
}
};
using SmallString = BasicSmallString<char>;
inline constexpr SmallString operator "" _str(const char* ptr, size_t size) {
return SmallString(ptr, size);
}
#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_SMALL_STRING_H

View File

@ -11,9 +11,9 @@
#include <concepts>
#include <ranges>
#include <string>
#include <string_view>
#include <type_traits>
#include "small_string.h"
#include "test_macros.h"
#include "test_iterators.h"
@ -55,18 +55,21 @@ static_assert( std::is_move_constructible_v<ForwardView>);
// Iterator types differ based on constness of this class.
struct ForwardDiffView : std::ranges::view_base {
SmallString buffer_;
std::string buffer_;
constexpr explicit ForwardDiffView() = default;
constexpr ForwardDiffView(const char* ptr) : ForwardDiffView(std::string_view(ptr)) {}
constexpr ForwardDiffView(std::string_view v) : buffer_(v) {}
constexpr ForwardDiffView(std::string_view v) {
// Workaround https://github.com/llvm/llvm-project/issues/55867
buffer_ = v;
}
constexpr ForwardDiffView(ForwardDiffView&&) = default;
constexpr ForwardDiffView& operator=(ForwardDiffView&&) = default;
constexpr ForwardDiffView(const ForwardDiffView&) = default;
constexpr ForwardDiffView& operator=(const ForwardDiffView&) = default;
constexpr forward_iterator<char*> begin() { return forward_iterator<char*>(buffer_.begin()); }
constexpr forward_iterator<char*> end() { return forward_iterator<char*>(buffer_.end()); }
constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(buffer_.begin()); }
constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(buffer_.end()); }
constexpr forward_iterator<char*> begin() { return forward_iterator<char*>(buffer_.begin().base()); }
constexpr forward_iterator<char*> end() { return forward_iterator<char*>(buffer_.end().base()); }
constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(buffer_.begin().base()); }
constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(buffer_.end().base()); }
};
static_assert( std::ranges::forward_range<ForwardView>);
static_assert( std::ranges::forward_range<const ForwardView>);
@ -135,21 +138,27 @@ static_assert( std::ranges::view<ForwardOnlyIfNonConstView>);
// InputView
struct InputView : std::ranges::view_base {
SmallString buffer_;
std::string buffer_;
constexpr InputView() = default;
constexpr InputView(const char* s) : InputView(std::string_view(s)) {}
constexpr InputView(std::string_view v) : buffer_(v) {}
constexpr InputView(std::string_view v) {
// Workaround https://github.com/llvm/llvm-project/issues/55867
buffer_ = v;
}
constexpr cpp20_input_iterator<char*> begin() { return cpp20_input_iterator<char*>(buffer_.begin()); }
constexpr cpp20_input_iterator<char*> begin() { return cpp20_input_iterator<char*>(buffer_.begin().base()); }
constexpr sentinel_wrapper<cpp20_input_iterator<char*>> end() {
return sentinel_wrapper(cpp20_input_iterator<char*>(buffer_.end()));
return sentinel_wrapper(cpp20_input_iterator<char*>(buffer_.end().base()));
}
constexpr cpp20_input_iterator<const char*> begin() const {
return cpp20_input_iterator<const char*>(buffer_.begin());
return cpp20_input_iterator<const char*>(buffer_.begin().base());
}
constexpr sentinel_wrapper<cpp20_input_iterator<const char*>> end() const {
return sentinel_wrapper(cpp20_input_iterator<const char*>(buffer_.end()));
return sentinel_wrapper(cpp20_input_iterator<const char*>(buffer_.end().base()));
}
friend constexpr bool operator==(const InputView& lhs, const InputView& rhs) {
return lhs.buffer_ == rhs.buffer_;
}
};