Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Choose function to apply based on the validity of an expression

The problem is the following, in C++14:

  • Let's have two functions FV&& valid_f, FI&& invalid_f, and arguments Args&&... args
  • The function apply_on_validity should apply valid_f on args if the expression std::forward<FV>(valid_f)(std::forward<Args>(args)...) is valid
  • Otherwise and if std::forward<FV>(invalid_f)(std::forward<Args>(args)...) is a valid expression, apply_on_validity should apply invalid_f on args
  • Otherwise apply_on_validity should do nothing

I guess the code should look like something like this:

template <class FV, class FI, class... Args, /* Some template metaprog here */>
void apply_on_validity(FV&& valid_f, FI&& invalid_f, Args&&... args)
{
    // Apply valid_f by default
    std::forward<FV>(valid_f)(std::forward<Args>(args)...);
}

template <class FV, class FI, class... Args, /* Some template metaprog here */>
void apply_on_validity(FV&& valid_f, FI&& invalid_f, Args&&... args)
{
    // Apply invalid_f if valid_f does not work
    std::forward<FV>(invalid_f)(std::forward<Args>(args)...);
}

template <class FV, class FI, class... Args, /* Some template metaprog here */>
void apply_on_validity(FV&& valid_f, FI&& invalid_f, Args&&... args)
{
    // Do nothing when neither valid_f nor invalid_f work
}

But I don't really know how to do that. Any idea?


Link to the generalization here.

like image 404
Vincent Avatar asked Feb 03 '17 17:02

Vincent


People also ask

What does '@' mean in Excel formula?

The @ symbol is already used in table references to indicate implicit intersection. Consider the following formula in a table =[@Column1]. Here the @ indicates that the formula should use implicit intersection to retrieve the value on the same row from [Column1].

How do you use the Choose function?

Use CHOOSE to select one of up to 254 values based on the index number. For example, if value1 through value7 are the days of the week, CHOOSE returns one of the days when a number between 1 and 7 is used as index_num.


1 Answers

Take:

template <int N> struct rank : rank<N-1> {};
template <> struct rank<0> {};

and then:

template <class FV, class FI, class... Args>
auto apply_on_validity_impl(rank<2>, FV&& valid_f, FI&& invalid_f, Args&&... args)
    -> decltype(std::forward<FV>(valid_f)(std::forward<Args>(args)...), void())
{
    std::forward<FV>(valid_f)(std::forward<Args>(args)...);
}

template <class FV, class FI, class... Args>
auto apply_on_validity_impl(rank<1>, FV&& valid_f, FI&& invalid_f, Args&&... args)
    -> decltype(std::forward<FI>(invalid_f)(std::forward<Args>(args)...), void())
{
    std::forward<FI>(invalid_f)(std::forward<Args>(args)...);
}

template <class FV, class FI, class... Args>
void apply_on_validity_impl(rank<0>, FV&& valid_f, FI&& invalid_f, Args&&... args)
{

}

template <class FV, class FI, class... Args>
void apply_on_validity(FV&& valid_f, FI&& invalid_f, Args&&... args)
{
    return apply_on_validity_impl(rank<2>{}, std::forward<FV>(valid_f), std::forward<FI>(invalid_f), std::forward<Args>(args)...);
}

DEMO

like image 119
Piotr Skotnicki Avatar answered Oct 07 '22 00:10

Piotr Skotnicki