这些代码片段没有什么特别之处,但它们提醒我们有时不使用for或while循环。甚至可以以类似的方式对struct成员进行迭代。
template <typename ...A>
constexpr auto all_loop(A&& ...a) noexcept
{
return [&](auto const f) noexcept(noexcept(
(f(std::forward<decltype(a)>(a)), ...)))
{
(f(std::forward<decltype(a)>(a)), ...);
};
}
template <typename ...A>
constexpr auto cond_loop(A&& ...a) noexcept
{
return [&](auto const f) noexcept(noexcept(
(f(std::forward<decltype(a)>(a)), ...)))
{
return (f(std::forward<decltype(a)>(a)) || ...);
};
}用法:
all_loop(1, 2, 3, false, true, nullptr)([](auto&& v) { std::cout << v << std::endl; });发布于 2021-08-06 12:42:34
我不认为有必要返回一个lambda,然后您必须调用它。为什么不将函数作为第一个参数传递,类似于std::apply和std::invoke?我会像这样重写all_loop():
template <typename F, typename ...A>
constexpr void invoke_all(F f, A&& ...a)
noexcept(noexcept((f(std::forward<decltype(a)>(a)), ...)))
{
(f(std::forward<decltype(a)>(a)), ...);
}然后你可以像这样使用它:
invoke_all([](auto&& v){std::cout << v << '\n';}, 1, 2, 3, false, true, nullptr);如果您确实需要将其作为lambda,则调用者仍然可以自己进行:
auto curried = [](auto const f){invoke_all(f, 1, 2, 3, false, true, nullptr);};
curried([](auto&& v){std::cout << v << '\n';});'\n'而不是std::endl使用'\n'而不是std::endl;后者等同于前者,但也强制输出刷新,这通常不是必要的,可能会影响性能。
我想要实现像
pipe(1, 2, 3) | f;这样的东西
您也可以这样做,方法是创建一个存储值和重载operator|以接受任何函数的类型。例如:
template <typename... A>
class pipe
{
std::tuple<A...> a;
public:
pipe(A&&... a): a{a...} {}
auto operator|(auto&& f) {
std::apply([&](auto&&... a){(f(a), ...);}, a);
}
};(我把所有的decltypes和std::forwards都留给了读者。)然后你就可以写:
pipe(1, 2, 3, false, true, nullptr) | [](auto&& v) { std::cout << v << '\n'; };但是我不会使用这个,而是坚持在C++中调用事物的惯用方式。
https://codereview.stackexchange.com/questions/265724
复制相似问题