重载按位 OR('|'),用于链接操作无法按预期工作

Overloading bitwise OR('|') for chaining operations not working as expected

本文关键字:操作 工作 链接 OR 重载 用于      更新时间:2023-10-16

我正在尝试超负荷位或'|'运算符,以便我可以一个接一个地链接不同的操作。

我已经实施了以下代码。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct Test
{
    explicit Test(vector<int> vdata) : data_(vdata) { }
    vector<int>& operator()()
    {
        return data_;
    }
    template<typename Pred>
    Test operator | (Pred P)
    {
        *this = P;
        return *this;
    }
    vector<int> data_;
};
template <typename Con, typename Pred>
Con Transform(Con& C, Pred P)
{
    vector<int> res;
    transform(begin(C()), end(C()),back_inserter(res),  P);
    return Con(res);
}
template <typename Con, typename Pred>
Con Filter(Con& C, Pred P)
{
    vector<int> res;
    remove_copy_if(begin(C()), end(C()), back_inserter(res), P);
    return Con(res);
}
int main()
{
    vector<int> vdata{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    auto DoubleIt = [](int& v) {
        return v *= 2;
    };
    auto Remove_Lteq4 = [](auto v) {
        return v <= 4;
    };
    auto Remove_divideby3=[](auto v) 
    {
        return !(v % 3);
    };
    Test test(vdata);
    Test test1 =  
     test | Filter(test, Remove_Lteq4) |  
     Transform(test, DoubleIt) | 
     Filter(test, Remove_divideby3);
    // output
    for (auto v : test1())
        cout << v << " ";            
}

该代码在CXXDROID上提供预期输出2.0_arm离线编译器,C 14/C 17,但我在在线编译器上获得了不同的结果

输入:vector = {1,2,3,4,5,6,7,8,9,10,11,12}采用序列的操作是滤波器值&lt; = 4然后将剩余的乘以2,然后滤波值可除以3

结果离线编译器(CXXDROID(预期输出:10、14、16、20、22实际输出:10、14、16、20、22

在线编译器实际输出:1,2,4,5,7,8,10,11(实际上,这是只有将remove_divideby3函数应用于输入时,您将获得的输出(。

我现在正在挣扎一段时间,无法找出不同输出的原因。有人可以告诉我在哪里犯错。如果我一次仅应用一项操作,则该代码正常工作。

如果有人可以回答加法问题,我也会非常好。

  1. 我需要编写复制构造函数/复制分配,移动构造函数和移动分配。

  2. 是我对对象的使用情况,可以按值和参考来传递和返回对象。我认为问题在这里的某个地方,可能会通过一个需要参考的对象。

  3. 是否需要超载'|'在全球级别。

注意:使用命名空间std;仅在我在移动设备上键入代码时才用于方便目的。

谢谢

template<class F>
struct pipe_func {
  F f;
  template<class Lhs>
  friend auto operator|( Lhs&& lhs, pipe_func rhs ) {
    return rhs.f( std::forward<Lhs>(lhs) );
  }
};
template<class F>
pipe_func(F)->pipe_func<F>;

有一个适合您的基础。pipe_target采用一个函数,当管道事物将其馈送到功能并返回结果时。

现在假设您要编写过滤器。

template<class Pred>
auto Filter( Pred p ) {
  return pipe_func{[p]( auto&& container ) {
    using std::begin; using std::end;
    using R = std::decay_t< decltype(container) >;
    R retval;
    std::remove_copy_if( begin(container), end(container), std::back_inserter(retval), p );
    return retval;
  }};
}

因此,filter是一个依据的函数。

它返回pipe_funcpipe_func中有一个应用谓词的lambda。

转换是相似的:

template<class Pred>
auto Transform( Pred p ) {
  return pipe_func{[p]( auto&& container ) {
    using std::begin; using std::end;
    using R = std::decay_t< decltype(container) >;
    R retval;
    std::transform( begin(container), end(container), std::back_inserter(retval), p );
    return retval;
  }};
}

测试代码看起来像:

std::vector<int> test1 =  
 vdata | Filter(Remove_Lteq4) |  
 Transform(DoubleIt) | 
 Filter(Remove_divideby3);

现场示例。

现在,一种解决方案,我们可以将两个参数的功能输入功能有点腥。该功能仍然认为它需要2个参数,因此将其传递第二个很棘手。

我会避免它。任何解决方案都将是黑客。

您正在这样做(我重新布置了管道以使其更容易阅读(:

Test test1 =  
 test | Filter(test, Remove_Lteq4)
      | Transform(test, DoubleIt)
      | Filter(test, Remove_divideby3);

让我们从后面开始。Filter(test, Remove_divideby3)做什么?它还给一个容器,该容器是满足Remove_divideby3test的所有元素。但是test是您开始的,它不取决于此操作的任何部分。其他FilterTransform返回什么都没关系,因为这些值都没有用作 Filter的输入。

这就是为什么您得到的东西与写作没有什么不同:

Test test1 = Filter(test, Remove_divideby3);

您的适配器具有将范围作为参数:

Filter(Transform(Filter(test, Remove_Lteq4), DoubleIt), Remove_divideby3)

使用管道:

test | Filter(Remove_Lteq4) | Transform(DoubleIt) | Filter(Remove_divideby3)

不是同时同时。