我正在尝试按位重载或“|”运算符,以便我可以一个接一个地链接不同的操作。
我已经实现了以下代码。
#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 函数,这实际上是您将获得的输出)。
我已经为此苦苦挣扎了一段时间,无法找出不同输出的原因。有人可以告诉我在哪里犯了错误。 如果我一次只应用一个操作,代码可以正常工作。
如果有人可以回答其他问题,我也将非常感激。
我是否需要编写复制构造函数/复制赋值、移动构造函数和移动赋值。
在按值和按引用传递和返回对象方面,我对对象的使用是否正确。我认为问题出在此处,可能是在需要引用的地方传递了一个对象。
是否需要重载'|'在全局范围内。
注意:使用命名空间标准;仅出于方便目的使用,因为我是在手机上输入代码的。
谢谢
最佳答案
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_func
。 pipe_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 个参数,因此向它传递第二个参数很棘手。
我会避免它。任何解决方案都是黑客。
关于c++ - 按位重载 OR ('|' ) 链接操作未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57240471/