c++ - 按位重载 OR ('|' ) 链接操作未按预期工作

标签 c++ operator-overloading c++17

我正在尝试按位重载或“|”运算符,以便我可以一个接一个地链接不同的操作。

我已经实现了以下代码。

#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} 按顺序应用的操作是 筛选值 <= 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. 是否需要重载'|'在全局范围内。

注意:使用命名空间标准;仅出于方便目的使用,因为我是在手机上输入代码的。

谢谢

最佳答案

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);

Live example .

现在,我们可以通过管道将两个参数传入函数的解决方案有点可疑;该函数仍然认为它需要 2 个参数,因此向它传递第二个参数很棘手。

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

关于c++ - 按位重载 OR ('|' ) 链接操作未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57240471/

相关文章:

C++ 运算符 [] 重载没有响应

c++ - 如何让我的模板只需要绝对必要的功能

c++ - 使用重载运算符 () 在 C++ 中复制构造函数

gcc - 赋值 : still not implemented in GCC? 中的 C++17 排序

c++ - C++::在构造函数退出之前通过指针调用Member函数

c++ - 是否有任何不属于 C++ 标准库的 STL header ?

c++ - 成员右值引用和对象生命周期

python - Pybind - 使用指向派生类的共享指针调用函数

c++ - const int 和 const double 在编译时的区别

c++ - 用c++编写一个简单的linux桌面环境