Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ expand variadic template arguments into a statement

I'm currently playing around with template metaprogramming. I'm trying to make a finite state machine by using tmp. I know that there are several implementations in the web but I want to implement one by myself as an exercise.

I have a class called Condition which is the base class for the condition of a transition between two states. One implementation is the AnyCondition class:

template<class Input, Input comp, Input ... comps >
class AnyCondition: public Condition<Input>
{    
public:
    AnyCondition() {}

    bool operator()(const Input& input) const override
    {
        return input == comp || AnyCondition<Input, comps...>()(input);
    }

};

The thing here is, that the compiler will expand this recursivly, which results in a lot of recursive calls at runtime due to the input parameter. It should be more efficent, if the expanded code would be a statement like:

    bool operator()(const Input& input) const override
    {
        return input == comp1 || input == comp2 || input == comp3...
    }

Is this possible somehow?

like image 352
Timo Avatar asked Jan 05 '23 18:01

Timo


1 Answers

C++17 solution - fold expression:

template <typename... Ts>
auto anyCondition(Ts... xs)
{
    return (xs || ...);
}

wandbox example


C++11 solution - for_each_argument:

template <typename TF, typename... Ts>
void for_each_argument(TF&& f, Ts&&... xs)
{
    (void)(int[]){(f(std::forward<Ts>(xs)), 0)...};
}

template <typename... Ts>
auto anyCondition(Ts... xs)
{
    bool acc = false;
    for_each_argument([&acc](bool x){ acc = acc || x; }, xs...);
    return acc;
}   

wandbox example

I gave a talk about this snippet at CppCon 2015:
CppCon 2015: Vittorio Romeo “for_each_argument explained and expanded"

like image 196
Vittorio Romeo Avatar answered Jan 28 '23 12:01

Vittorio Romeo