Skip to content

Instantly share code, notes, and snippets.

@talybin
Last active August 19, 2021 13:19
Show Gist options
  • Select an option

  • Save talybin/9283b245659ff5d0f025f9d9e6dc2b0e to your computer and use it in GitHub Desktop.

Select an option

Save talybin/9283b245659ff5d0f025f9d9e6dc2b0e to your computer and use it in GitHub Desktop.
List of depended functions
#include <iostream>
template <class F>
struct waterfall
{
waterfall(F&& f)
: fn(std::forward<F>(f))
{}
template <class... Args>
decltype(auto) operator()(Args&&... args) const {
return fn(std::forward<Args>(args)...);
}
template <class T>
auto then(T&& t) const & {
return then_impl(fn, std::forward<T>(t));
}
template <class T>
auto then(T&& t) const && {
return then_impl(std::move(fn), std::forward<T>(t));
}
private:
F fn;
template <class In, class Out>
static auto then_impl(In&& in, Out&& out)
{
auto fn = [in = std::forward<In>(in), out = std::forward<Out>(out)](auto&&... args)
{
using InRet = std::invoke_result_t<In, decltype(args)...>;
if constexpr (std::is_invocable_v<Out, InRet>) {
return out(in(std::forward<decltype(args)>(args)...));
}
else {
in(std::forward<decltype(args)>(args)...);
return out();
}
};
return waterfall<decltype(fn)>(std::move(fn));
}
};
int main()
{
// Function signature for t will be: int(const char*)
waterfall t([](const char* s) {
std::cout << "1: " << s << '\n';
return 42;
});
// Function signature for tt will be: double(const char*)
auto tt = t
.then([](auto x) {
// Type of x is int here
std::cout << "2: " << x << '\n';
return x + 1;
})
.then([] {
std::cout << "3: taking void\n";
return 5.2;
});
double ret = tt("test");
std::cout << "ret: " << ret << '\n';
// tt should not steal lambdas from t
t("calling first function only");
}
@talybin

talybin commented Aug 24, 2020

Copy link
Copy Markdown
Author
1: test
2: 42
3: taking void
ret: 5.2
1: calling first function only

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment