operator| 是如何重载的专门实施 C++ 范围适配器?

How is overloaded operator| implemented specifically c++ range adaptors?

自从范围被合并到 C++ 20 中,我一直在查看 headers 以了解 operator| 是如何为范围视图重载的,但我找不到关于如何或如何重载的正确轨道它在哪里实施。


根据 https://en.cppreference.com/w/cpp/ranges

C(R) 等同于 R | C,基于我所阅读的内容。

或者,V(R, F)等同于R | V(F),其中V是范围适配器object,R是可视范围,F 是任何可调用的 object 包括自由函数。


我已经阅读 What are the basic rules and idioms for operator overloading? 并且已经知道如何正确重载运算符,但是我找不到关于需要什么函数参数或模板参数,或者语法含义的指南,来满足上述实施要求。

我的意思不是要替换范围适配器的所有信息,而只是替换它在重载 operator|.

的适配器范围上的语法特征

还有一个就是管道后得到的object类型必须和容器的类型一样,只要满足下面的概念即可。

我的想法:

template <std::ranges::viewable_range Ran, std::invocable Inv>
auto operator|(Ran cont, Inv func) {
    /* ... */ 
} 

一些应用(假设我们已经实现了功能):

std::vector<int> vect1 {10, 3, 5, 3};
auto new_vect1 = vect1 | myfilter([](auto x){ return x % 3 == 0; });
// where new_vect1 is still `std::vector<int>`

其中 myfilter:

template <std::viewable_range T, std::invocable F>
decltype(auto) myfilter(T container, F func);

但我认为我的想法要么完全错误,要么在某些方面是错误的,其中大部分都被遗漏了。

这是基本结构:

template<std::ranges::viewable_range Range, other_concepts... OtherArgs>
new_range_t my_view(Range range, OtherArgs... args);

template<other_concepts... OtherArgs>
/* some type */ my_view(OtherArgs... args);

template<std::ranges::viewable_range Range, other_concepts... OtherArgs>
new_range_t operator|(Range range, /* some type */ holder);

您可以使用具有两个 operator() 模板的对象来代替一对函数模板。

struct my_view_t {
    template<std::ranges::viewable_range Range, other_concepts... OtherArgs>
    new_range_t operator()(Range range, OtherArgs... args);

    template<other_concepts... OtherArgs>
    /* some type */ operator()(OtherArgs... args);
} my_view;

OtherArgs... 可能不是参数包,但它表示您的视图采用的任何其他参数。如果它是一个参数包,你必须确保第二个参数永远不是一个范围,这样 my_view(R, args...)R | my_view(args...) 对于哪个重载就不会模棱两可。

在没有任何其他参数的特定情况下,您可以让一个对象执行双重任务。

struct nullary_view_t {
    template<std::ranges::viewable_range Range>
    new_range_t operator()(Range range);

    template<std::ranges::viewable_range Range>
    friend new_range_t operator|(Range range, nullary_view_t);
} nullary_view;