将operator|
泛化:
template<typename LeftT, typename RightT>
auto operator|(LeftT&& left, RightT&& right)
-> decltype(std::forward<RightT>(right)(std::forward<LeftT>(left)))
{return std::forward<RightT>(right)(std::forward<LeftT>(left))
现在,这允许您对整个代码库中的任何值和一元函数应用value | single_arg_method
,但是如果您在无辜的|
附近打字错误,则会使编译器错误变得更加复杂。
然后唯一的技巧就是使add(15)
生成所需的一元函数。我无法想到没有使用宏将此函数重命名为调用它的方法名称的方法。
#define define_bifunction_to_monofunction(name) \
template<class ArgT> \
auto name(ArgT&& right) { \
return [&right](auto&& left){ \
return _ ## name(std::forward<decltype(left)>(left), std::forward<ArgT>(right)); \
}; \
}
对于宏的了解比我更多的人可能知道如何使用##
来调用_add
而不是add
。
现在,使用变得简单:
string _add(int&& a1, float&& a2)
{
return "ADD i:" + to_string(a1) + " f:" + to_string(a2);
}
define_bifunction_to_monofunction(add)
int main() {
string s1 = 10.f | add(15);
string s2 = 10 | add(15);
string s3 = 10 | add(10.f);
}
http://coliru.stacked-crooked.com/a/30697aebc0d594ac
然而,这确实使得operator|
过于激进,可能会导致奇怪的编译器错误,因此通常建议制定某种类型标志,这会稍微复杂化实现:
template<typename FunctionT>
struct enabled_pipe_chaining : std::false_type {};
template<typename LeftT, typename RightT, typename enabled=std::enable_if_t<enabled_pipe_chaining<RightT>::value,void> >
auto operator|(LeftT&& left, RightT&& right)
{return std::forward<RightT>(right)(std::forward<LeftT>(left));}
#define enable_mono_pipe_chain(name) \
template<> struct enabled_pipe_chaining<decltype(name)> : std::true_type {};
#define define_bifunction_pipe_chain(name) \
template<typename RightT> \
struct name ## _pipe_chainable { \
RightT&& right; \
template<typename LeftT> \
auto operator()(LeftT&& left) { \
return _ ## name(std::forward<decltype(left)>(left), std::forward<RightT>(right)); \
} \
}; \
template<typename RightT> struct enabled_pipe_chaining<name ## _pipe_chainable<RightT>> : std::true_type {}; \
template<typename RightT> \
name ## _pipe_chainable<RightT> name(RightT&& right) { return {std::forward<RightT>(right)};}
http://coliru.stacked-crooked.com/a/41ce66c1a1444495
但是operator|
仅适用于pipe_chainable方法,而不是代码中的任何operator|
。
args
是什么。 - Jarod42operator()
)代替函数吗? - Jarod42_add
是一个保留符号。可能会导致一些问题。 - Eljay