【发布时间】:2021-06-17 13:05:32
【问题描述】:
是否可以在 C++ 20 中实现通用的多函子组合/流水线?
struct F{//1st multi-functor
template<typename T> void operator()(const T& t){/*...*/}
};
struct G{//2nd multi-functor
template<typename T> void operator()(const T& t){/*...*/}
};
F f;
G g;
auto pipe = f | g;//what magic should happen here to achieve g(f(...)) ? how exactly to overload the operator|()?
pipe(123); //=> g(f(123);
pipe("text");//=> g(f("text");
编辑: 我尝试了这两个建议(来自@Some_programmer_dude 和@Jarod42),但我迷失在错误中:
- 像@Some_programmer_dude 建议的重载运算符|()
template<class Inp, class Out>
auto operator|(Inp inp, Out out){
return [inp,out](const Inp& arg){
out(inp(arg));
};
}
生成:
2>main.cpp(71,13): error C3848: expression having type 'const Inp' would lose some const-volatile qualifiers in order to call 'void F::operator ()<F>(const T &)'
2> with
2> [
2> Inp=F
2> ]
2> and
2> [
2> T=F
2> ]
- 直接使用 lambda,而不是像 @Jarod42 建议的那样重载 operator|():
auto pipe = [=](const auto& arg){g(f(arg));};
生成:
2>main.cpp(86,52): error C3848: expression having type 'const F' would lose some const-volatile qualifiers in order to call 'void F::operator ()<_T1>(const T &)'
2> with
2> [
2> _T1=int,
2> T=int
2> ]
【问题讨论】:
-
您需要一个
operator|函数,它在左侧接受一个F对象,在右侧接受一个G对象。然后它可以返回一个 lambda,当被调用时做你想做的事。 -
auto pipe = [=](const auto& arg){ g(f(arg)); };:-) -
lambda 的参数类型与您尝试调用它的类型不同。您确实需要对 lambda 参数使用自动类型推导。现在,lamda 的参数类型是
const F&(使用您当前拥有的代码)。请参阅@Jarod42 的评论。 -
“会丢失一些 const-volatile 限定符”是因为您的
operator()s 不是const
标签: c++ templates pipeline c++20 functor