Skip to content

Commit

Permalink
[libc++][test] Refactor SmallBasicString uses in range.lazy.split tests
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JoeLoser committed Jun 11, 2022
1 parent 11f75e0 commit ae2ae84
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 132 deletions.
Expand Up @@ -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`.
{
Expand Down
Expand Up @@ -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 {
Expand Down Expand Up @@ -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_; }
Expand All @@ -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);
}
Expand Down
Expand Up @@ -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>>;
Expand Down Expand Up @@ -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;
Expand Down
Expand Up @@ -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);
Expand All @@ -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));
}
}

Expand Down
Expand Up @@ -17,35 +17,36 @@
#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", " ");

// ++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));
}
}

Expand All @@ -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));
}
}

Expand Down

This file was deleted.

35 changes: 22 additions & 13 deletions libcxx/test/std/ranges/range.adaptors/range.lazy.split/types.h
Expand Up @@ -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"

Expand Down Expand Up @@ -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>);
Expand Down Expand Up @@ -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_;
}
};

Expand Down

0 comments on commit ae2ae84

Please sign in to comment.