gpt4 book ai didi

c++ - 您如何使用运算符 | 创建与现有 View 交互的自己的 View ?

转载 作者:行者123 更新时间:2023-12-03 10:03:33 25 4
gpt4 key购买 nike

为什么此代码适用于 #if 0阻止到位,但如果删除它,则会失败并显示一组相当复杂的错误消息?更重要的是,我如何使它与上面非常相似的块得到相同的结果?

#include <ranges>
#include <iterator>
#include <optional>
#include <string_view>
#include <iostream>
#include <algorithm>

template <::std::ranges::view View,
typename Pred>
requires ::std::ranges::input_range<View> &&
::std::ranges::common_range<View> &&
::std::is_object_v<Pred> &&
::std::indirect_unary_predicate<const Pred, ::std::ranges::iterator_t<View>>
class skip_after_view : public ::std::ranges::view_interface<skip_after_view<View, Pred>>
{
public:
skip_after_view() = default;
skip_after_view(View v, Pred p)
: subview_(::std::move(v)), pred_(::std::move(p))
{}
class iterator;
friend class iterator;

auto begin() const {
return iterator{subview_.begin(), subview_.end(), &pred_};
}
auto end() const {
return iterator{subview_.end(), subview_.end(), &pred_};
}

private:
View subview_ = View();
Pred pred_;
};

template <typename View, typename Pred>
class skip_after_view<View, Pred>::iterator
{
using parent_t = View::iterator;
using parent_traits = ::std::iterator_traits<parent_t>;
friend class skip_after_view<View, Pred>;
public:
using value_type = parent_traits::value_type;
using reference = parent_traits::reference;
using pointer = parent_traits::pointer;
using difference_type = ::std::ptrdiff_t;
using iterator_category = ::std::input_iterator_tag;

constexpr iterator() = default;

auto operator *() { return *me_; }
auto operator *() const { return *me_; }
iterator &operator ++() {
for (bool last_pred = true; last_pred; ) {
if (end_ != me_) {
last_pred = (*pred_)(operator *());
++me_;
} else {
last_pred = false;
}
}
return *this;
}
void operator ++(int) {
++(*this);
}
friend
bool operator ==(iterator const &a, iterator const &b) {
return a.me_ == b.me_;
}

private:
parent_t me_;
parent_t end_;
Pred const *pred_ = nullptr;

iterator(parent_t const &me, parent_t end, Pred const *pred)
: me_(me), end_(::std::move(end)), pred_(pred)
{}
};

template <std::ranges::range Range, typename Pred>
skip_after_view(Range&&) -> skip_after_view<std::ranges::views::all_t<Range>, Pred>;

struct skip_after_adaptor {

template <typename Pred>
class closure {
friend class skip_after_adaptor;
Pred pred;

explicit closure(Pred &&p) : pred(::std::move(p)) {}
public:
template <typename Range>
auto operator ()(Range &&range) {
return skip_after_view(::std::forward<Range>(range),
::std::move(pred));
}
};
template <typename Pred>
auto operator ()(Pred pred) const {
return closure<Pred>(::std::move(pred));
}
template <typename Range, typename Pred>
auto operator()(Range &&range, Pred &&pred) const {
return skip_after_view(::std::forward(range), ::std::forward(pred));
}
template <typename Range, typename Pred>
friend auto operator|(Range&& rng, closure<Pred> &&fun) {
return fun(std::forward<Range>(rng));
}
};

constexpr auto skip_after = skip_after_adaptor{};

template <::std::input_iterator it>
void check(it const &)
{}

int main()
{
using ::std::string_view;
using namespace ::std::ranges::views;
using ::std::ostream_iterator;
using ::std::ranges::copy;
using ::std::cout;
auto after_e = [](char c) { return c == 'e'; };

constexpr string_view sv{"George Orwell"};
int sum = 0;
{
cout << '[';
copy(sv | skip_after(after_e) | take(6),
ostream_iterator<char>(cout));
cout << "]\n";
}
#if 0
{
auto tmp = skip_after(after_e) | take(6);
cout << '[';
copy(sv | tmp, ostream_iterator<char>(cout));
cout << "]\n";
}
#endif
return sum;
}
Obligatory Compiler Explorer link
如果我想要的东西完全不可能,有没有丑陋的方法来做到这一点?例如,我是否可以创建自己的组合机制并使用一堆丑陋的垃圾将其与现有 View 连接起来。

最佳答案

无法编写与 C++20 中的标准对象组合的范围适配器闭包对象。标准库不公开它用于该组合的机制。sv | skip_after(after_e) | take(6)有效是因为 sv | skip_after(after_e)击中您的 operator| ,产生 view然后可以与 take(6) 一起使用.
C++23 很有可能会公开组合机制。

关于c++ - 您如何使用运算符 | 创建与现有 View 交互的自己的 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64649664/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com