Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用运算符|创建与现有视图交互的自己的视图?_C++_G++_C++20_Libstdc++_Std Ranges - Fatal编程技术网

C++ 如何使用运算符|创建与现有视图交互的自己的视图?

C++ 如何使用运算符|创建与现有视图交互的自己的视图?,c++,g++,c++20,libstdc++,std-ranges,C++,G++,C++20,Libstdc++,Std Ranges,为什么此代码可以在适当的#if 0块中工作,但如果删除它,则会失败并显示一组相当复杂的错误消息?更重要的是,我如何使它与上面非常相似的块得到相同的结果 #include <ranges> #include <iterator> #include <optional> #include <string_view> #include <iostream> #include <algorithm> template <::

为什么此代码可以在适当的
#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;
}
#包括
#包括
#包括
#包括
#包括
#包括


如果我想要的不是完全可能的,有没有丑陋的方法?例如,我可以创建自己的组合机制,并使用一堆丑陋的垃圾将其与现有视图进行交互。

无法编写与C++20中的标准对象组合的范围适配器闭包对象。标准库不公开它用于该合成的机制

sv|skip|u after(after|e)| take(6)
之所以有效,是因为
sv|skip|u after(after|e)
点击您的
操作符
,它会生成一个
视图
,然后可以与
take(6)
一起使用


C++23很有可能会暴露组合机制。

一个隐藏在简单问题伪装下的复杂问题。出于好奇:使用表达式模板不是一种解决方法/黑客吗?@darune-example?我就是这么想的。我研究了现有适配器如何使用合成机制,它看起来完全是库内部的。我问这个只是想看看我是否遗漏了什么。你对现在如何创作它们有什么建议吗,即使它真的很难看或乏味?例如,我是否可以创建自己的合成机制,并使用一堆丑陋的垃圾将其与现有视图进行交互,以便在有更好的方法时删除这些视图?