2
\$\begingroup\$

These snippets are nothing special, but they remind us to sometimes loop without a for or a while loop. It is even possible to iterate over struct members in a similar manner.

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)) || ...);
 };
}

Usage:

all_loop(1, 2, 3, false, true, nullptr)([](auto&& v) { std::cout << v << std::endl; });

https://wandbox.org/permlink/kFnaNn1vPoS0lF4F

asked Aug 5, 2021 at 11:07
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

No need to return a lambda

I don't see the need for returning a lambda which you then have to invoke. Why not pass the function as the first parameter, similar to std::apply and std::invoke? I would rewrite all_loop() like so:

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)), ...);
}

And then you can use it like so:

invoke_all([](auto&& v){std::cout << v << '\n';}, 1, 2, 3, false, true, nullptr);

If you really need to have it as a lambda, the caller can still do that themselves:

auto curried = [](auto const f){invoke_all(f, 1, 2, 3, false, true, nullptr);};
curried([](auto&& v){std::cout << v << '\n';});

Prefer '\n' over std::endl

Use '\n' instead of std::endl; the latter is equivalent to the former, but also forces the output to be flushed, which is normally not necessary and might impact performance.

Making it "pipeable"

I wanted to achieve something like pipe(1, 2, 3) | f;

You can do that as well, by creating a type that stores the values and overloads operator| to take any function. For example:

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);
 }
};

(I left all the decltypes and std::forwards as an excercise to the reader.) Then you can indeed write:

pipe(1, 2, 3, false, true, nullptr) | [](auto&& v) { std::cout << v << '\n'; };

But I would not use this, and rather stick to the idiomatic way of calling things in C++.

answered Aug 6, 2021 at 12:42
\$\endgroup\$
9
  • \$\begingroup\$ I wanted to separate the loop "body" from the arguments. We usually don't think of this sort of thing as "looping". \$\endgroup\$ Commented Aug 6, 2021 at 14:27
  • \$\begingroup\$ i.e. I wanted to achieve something like pipe(1, 2, 3) | f; \$\endgroup\$ Commented Aug 6, 2021 at 14:40
  • 1
    \$\begingroup\$ @user1095108 Yes, and then you also need to add the perfect forwarding. That's why I said I left it as an excercise. I think that should not be a problem, you did this correctly in your code! \$\endgroup\$ Commented Aug 6, 2021 at 15:35
  • 1
    \$\begingroup\$ Oh, I wasn't claiming that! Only saying that like we got used to << and >> not just being bit-shift but also streaming back in the 1980s, and that other libraries have followed that lead, we might start to see use of | as a composition operator more widely, following its use in Ranges. I'm not really advocating that in 2021, though - just musing on the way idioms can change. \$\endgroup\$ Commented Aug 6, 2021 at 15:42
  • 1
    \$\begingroup\$ if std::tuple were more inspired, we could just do std::forward_as_tuple(1, 2, 3) | f. \$\endgroup\$ Commented Aug 6, 2021 at 15:54

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.