好没问题。
template<class Lhs, class F>
struct foldable_binop_t {
Lhs lhs;
F f;
template<class Rhs>
auto operator*(Rhs&& rhs) &&
-> foldable_binop_t< std::result_of_t<F&(Lhs&&, Rhs&&)>, F >
{
return { f(std::forward<Lhs>(lhs), std::forward<Rhs>(rhs)), std::forward<F>(f) };
}
Lhs operator()() && { return std::forward<Lhs>(lhs); }
operator Lhs() && { return std::move(*this)(); }
Lhs get() && { return std::move(*this); }
};
template<class F>
struct foldable_t {
F f;
template<class Lhs>
friend foldable_binop_t<Lhs, F> operator*( Lhs&& lhs, foldable_t&& self ) {
return {std::forward<Lhs>(lhs), std::forward<F>(self.f)};
}
template<class Rhs>
foldable_binop_t<Rhs, F> operator*( Rhs&& rhs ) && {
return {std::forward<Rhs>(rhs), std::forward<F>(f)};
}
};
template<class F>
foldable_t<F> foldable(F f) { return {std::move(f)}; }
测试代码:
template<class...Xs>
auto result( Xs... xs ) {
auto maxer = [](auto&&...args){return (std::max)(decltype(args)(args)...);};
return ((0 * foldable(maxer)) * ... * xs).get();
}
template<class...Xs>
auto result2( Xs... xs ) {
auto maxer = [](auto&&...args){return (std::max)(decltype(args)(args)...);};
return (foldable(maxer) * ... * xs).get();
}
int main() {
int x = result2( 0, 7, 10, 11, -3 ); // or result
std::cout << x << "\n";
}
活生生的例子。
我个人觉得
auto maxer = [](auto&&...args){return (std::max)(decltype(args)(args)...);};
一直写很烦,所以
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...) \
[](auto&&...args) \
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
让它
template<class...Xs>
auto result3( Xs... xs ) {
return (foldable(OVERLOADS_OF((std::max))) * ... * xs).get();
}
甚至
template<class...Xs>
constexpr auto result4( Xs... xs )
RETURNS( (foldable(OVERLOADS_OF((std::max))) * ... * xs).get() )
这似乎更具表现力,并且得到 noexcept / constexpr 正确,等等。