当然,所有这些对于普通的函数参数来说都是微不足道的。
除非用于学习和玩具示例,否则我不建议使用逗号运算符。不要把它放在生产代码中。
但是使用逗号操作符对于增量和 re-currying 也很有趣。这是一个工作示例:
template<typename F, typename... Curry>
struct comma_curry {
template<typename... C>
explicit comma_curry(F function, C&&... c) noexcept :
function(std::move(function)), curry{std::forward<C>(c)...} {}
template<typename T>
friend auto operator,(comma_curry&& self, T&& arg) -> comma_curry<F, Curry..., std::decay_t<T>> {
return std::apply([&](auto&&... curry) {
return comma_curry<F, Curry..., std::decay_t<T>>(std::move(self.function), std::forward<decltype(curry)>(curry)..., std::forward<T>(arg));
}, std::move(self.curry));
}
template<typename... Args>
auto operator()(Args&&... args) const& -> decltype(auto) {
return std::apply([&](auto&&... curry) -> decltype(auto) {
return function(std::forward<decltype(curry)>(curry)..., std::forward<Args>(args)...);
}, curry);
}
template<typename... Args>
auto operator()(Args&&... args) && -> decltype(auto) {
return std::apply([&](auto&&... curry) -> decltype(auto) {
return std::move(function)(std::forward<decltype(curry)>(curry)..., std::forward<Args>(args)...);
}, std::move(curry));
}
private:
// [[no_unique_address]]
F function;
// [[no_unique_address]]
std::tuple<Curry...> curry;
};
它支持通过currying引用std::ref
并支持currying move only types。
它可以这样使用:
int main() {
auto function = [](int& i, double, std::unique_ptr<int>, std::tuple<int>) {
std::cout << "Called! i value: " << i << std::endl;
};
int number = 1;
// Reference arguments are sent using std::ref
auto curried = (comma_curry(function), std::ref(number), 1.5);
curried(std::make_unique<int>(), std::tuple{1});
number = 42;
auto recurried = (std::move(curried), std::make_unique<int>(), std::tuple{1});
// We curried a std::unique_ptr, our function is a one time call
// Since it's a one time call and destroy itself in the calling,
// it must be moved
std::move(recurried)();
}
活生生的例子