This previous answer shows how to apply function based on the validity of a call: here. However, it applies to two functions. I was wondering if the concept could be general
The syntax you are using is kind of awkward, since you have to know exactly how many functions you have. Combined with Piotr Skotnicki's solution, this solves that problem:
// Would be a local class except for the fact that it needs
// to have templates, thus can't be local to the function.
template
class apply_first_f final {
public:
apply_first_f(Fs&&... fs)
: fs_{ std::forward(fs)... }
{}
template
decltype(auto) operator()(Args&&... args) const
{
return apply_impl(std::make_index_sequence{}, std::forward_as_tuple(std::forward(args)...));
}
private:
std::tuple...> fs_;
template
decltype(auto) apply_impl(std::index_sequence, Args&& args) const
{
return apply_on_validity_impl(
0,
std::integral_constant{},
std::make_index_sequence{},
std::tuple_cat(
std::forward_as_tuple(std::get(fs_)...),
std::forward(args)
)
);
}
};
template
auto make_apply_first_valid_f(Fs&&... fs)
{
return apply_first_f{ std::forward(fs)... };
}
And the function can be used like so:
make_apply_first_valid_f(f1, f2, f3)(args);
DEMO (adapted from Piotr's demo)
Using it with Piotr's C++ 1z example requires just a small change:
template
class apply_first_f final {
// ...
template
decltype(auto) apply_impl(std::index_sequence, Args&& args) const
{
return apply_on_validity_impl(
/* 0, */
/* std::integral_constant{}, */
std::make_index_sequence{},
std::tuple_cat(
std::forward_as_tuple(std::get(fs_)...),
std::forward(args)
)
);
}
// ...
};