0

I have an EntityComponent-System and there's one component which should call functions on various other components. For this example here I've chosen a simple combination of the results of a boolean function.

The ResultCombinerComponent has variadic template arguments and for each of these arguments it should call a function, in the order that the template arguments are given. The order is very important.

Afterwards the results of the function calls are combined.

In the code below I just replaced the parts that I don't know how to achieve with psuedo-C++

template<typename... Args>
class ResultCombinerComponent
{
    template<typename T> 
    bool calcSingleResult()
    {
        return getComponent<T>()->calcResult();
    }

    bool calcResult()
    {
        bool result = true;
        for (int i = 0; i < sizeof...(Args); i++)  // doesn't work
        {
            if (!calcSingleResult<Args(i)>()  // doesn't work
            {
                result = false;
                break;
            }
        }
        return result;
    }

}


class A
{ 
    bool calcResult();
}
class B
{ 
    bool calcResult();
}
class C
{ 
    bool calcResult();
}
keyboard
  • 2,137
  • 1
  • 20
  • 32
  • [This](http://stackoverflow.com/questions/12030538/calling-a-function-for-each-variadic-template-argument-and-an-array) could give you some info. – LogicStuff Apr 30 '16 at 12:25
  • I've read this and many other similar posts a couple of times and tried to apply it to my specific problem, but couldn't apply it to my specific problem yet. – keyboard Apr 30 '16 at 12:29
  • You aren't using `...` (parameter pack expansion) anywhere. One more thing - you want to calculate something with just the provided types? ... because there are no actual instances/objects in your code. – LogicStuff Apr 30 '16 at 12:32
  • No, I added three more dummy classes with the calcResult() function. – keyboard Apr 30 '16 at 12:41
  • Can you please make this code syntactically correct. You're missing a parentheses in `calcResult()`'s `if()` statement. You are missing semicolons at the end of your class definitions. – bku_drytt Apr 30 '16 at 12:43
  • 1
    If it's not critical that you stop the loop as soon as the first `false` is encountered, you could replace it with `bool results[] = { calcSingleResult()... };`. – melak47 Apr 30 '16 at 13:05
  • @melak47 What if I wanted a short-cirtuit evaluation? Is it possible? – LogicStuff Apr 30 '16 at 13:20
  • I just tried what @melak47 said and it works, but only in the context of creating an array...if my function had void return type - how could I simply call the function for all template parameters? – keyboard Apr 30 '16 at 13:29
  • You can find various solutions to that, e.g. `int stuff[] = { (voidfun(),0)... };`. In C++1z, fold expressions and the comma operator handle the void case without such cruft. – melak47 Apr 30 '16 at 13:47

1 Answers1

2

in C++17, you may do:

bool calcResult()
{
    return (calcSingleResult<Args>() && ...);
}

In c++11, you have to have other methods:

template <typename T>
bool calcImpl()
{
    return calcSingleResult<T>();
}

template <typename T, typename T2, typename...Ts>
bool calcImpl()
{
    return calcSingleResult<T>() && calcImpl<T2, Ts...>();
}

bool calcResult()
{
    return calcImpl<Args...>();
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302