【发布时间】:2021-06-18 11:48:18
【问题描述】:
是否可以在管道功能和优雅的语法(如管道)中链接 3 个或更多多功能函数?
struct Filter0{//multi-functor; will be the last one in pipeline
template<Args...args> void operator()(Args&&...args){/*not important what is done here*/}
};
template<std::invocable F> struct Filter1{//intermediate filter forwarding to a multi-functor
template<Args...args> void operator()(F&f, Args&&...args){
/*do smtg and sometime call f(std::forward<decltype(args)>(args)...);*/
}
};
template<typename Left, std::invocable Right>
auto operator|(Left left, Right right){//chains "something" with a multi-functor
return [left,right](auto&& arg){
left(right, std::forward<decltype(arg)>(arg));
};
}
Filter0 filter0;
Filter1<decltype(Filter0)> filter1;
auto pipe1 = filter1 | filter0;//OK
pipe1('x');//OK pushes 'x' down the pipeline
Filter2<decltype(Filter1)> filter2;//Filter2 would be something similar with Filter1
auto pipe2 = filter2 | (filter1 | filter0);//KO
pipe2('x');//KO
第一个 KO 行中有或没有括号:
- 我认为带有括号的“(filter1 | filter0)”应该以某种方式返回一个仿函数
- 没有括号我认为“filter2 | filter1”应该以某种方式返回一个部分函数
注意:如果我为每个中间过滤器提供“下一个”作为 ctor 的参数并将其作为成员存储在类中而不是在每个方法中作为参数,我可以“链接”3 个或更多过滤器,例如:
Filter0 filter0;
Filter1 filter1(filter0);
Filter2 filter2(filter1);
filter2('x');//this will push 'x' down the pipeline
但在这种情况下,它们从声明中彼此“紧密”。 我希望它们尽可能“松散”,仅按类型“紧”(如果可能的话,甚至根本不)
你可以在这里玩一个活生生的例子:https://godbolt.org/z/6e8cfrbTo
解决方案 1(简单而简短):将模板参数从过滤器类移动到方法(感谢 RedFog 和 Jarod42!)
解决方案 2(稍微详细一点):将 filter|filter 操作设为表达式模板(参见 https://godbolt.org/z/G9z3qfsj8)
【问题讨论】:
-
你的问题是
Filter2<decltype(Filter1)> filter2是错的,应该是Filter2<decltype(pipe1)> filter2Demo。 -
F 是类的模板参数而不是函数的模板参数有什么原因吗?
-
std::invocable的用法很奇怪:你期望f(),但用不同类型的参数调用它。
标签: c++ templates pipeline functor