c++ - 为链接操作重载按位 OR('|') 无法按预期工作
问题描述
我正在尝试按位重载 OR '|' 运算符,这样我就可以一个接一个地链接不同的操作。
我已经实现了以下代码。
#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>;
有一个适合你的积木。Apipe_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 个参数,因此传递它的第二个参数是很棘手的。
我会避免它。任何解决方案都将是一个黑客。
推荐阅读
- python - 我正在尝试将 html 表存储到 pandas 数据框中。但我收到一个错误,TypeError: Cannot read object of type 'WebElement'
- html - 点击表格链接
- html - 当填充为零时,为什么不考虑前导/尾随边距?
- image - 使用个人图像创建 SwiftUI 按钮
- javascript - react-native中如何根据数组值生成动态UI
- php - 我想在索引页面上显示所有活动用户,但始终显示零值
- ios - 为什么我的 HTML 字符串在 WebView iOS 中没有显示正确的 html 标签?
- java - 如何实现嵌套函数的访问者模式
- html - 如何在 css 中创建多类选择器?
- laravel - 在 null 上调用成员函数 delete()