Karl Sassie
Karl Sassie

Reputation: 43

How to Iterate over number of variadic template Types

I'am currently learning C++ and i am currently building a very simple Entity Component System. For that i have a Function getComponentType which maps each Component to a uint8_t. A Signature is just a std::bitset

I would like a method like this.

Signature signature = createSignature<TransformComponent, GraphicsComp>();

Lets say TransformComponent gets mapped to 0 and GraphicsComp get mapped to 1. The Signature should now be a std::bitset {1100000...} I know how to do that with non various template methods, the Question is now how would i archive the same with various template types or is there a better solution to do the same.

    template <typename T> Signature createSignature(){
        return Signature(((unsigned long long int)1)<<getComponentType<T>());
    }

    template <typename T, typename R> Signature createSignature(){
        return Signature(
                ((unsigned long long int)1)<<getComponentType<T>() |
                ((unsigned long long int)1)<<getComponentType<R>()
                );
    }

    template <typename T, typename R, typename S> Signature createSignature(){
        return Signature(
                ((unsigned long long int)1)<<getComponentType<T>() |
                ((unsigned long long int)1)<<getComponentType<R>() |
                ((unsigned long long int)1)<<getComponentType<S>()
                );
    }

    template <typename T, typename R, typename S, typename U> Signature createSignature(){
        return Signature(
                ((unsigned long long int)1)<<getComponentType<T>() |
                ((unsigned long long int)1)<<getComponentType<R>() |
                ((unsigned long long int)1)<<getComponentType<S>() |
                ((unsigned long long int)1)<<getComponentType<U>()
                );
    }

Upvotes: 0

Views: 131

Answers (2)

speed_of_light
speed_of_light

Reputation: 66

I believe variadic templates are the way to go here. Something along the lines of

template<typename T>
Signature createSignature(T t)
{
    return Signature(((unsigned long long int)1)<<getComponentType<T>());
}

template <typename T, typename ...Args>
Signature createSignature(T t, Args ...args)
{
    return Signature(((unsigned long long int)1)<<getComponentType<T>()) | createSignature(args...);
}

Upvotes: 0

Andreas Loanjoe
Andreas Loanjoe

Reputation: 2399

From C++ 17 onward you could use a fold expression:

template<typename... T>
Signature createSignature()
{
   Return Signature((((unsigned long long int)1) << getComponentType<T>() | ...));
} 

The unsigned long long int cast seems a bit weird, but I left it the same as the question to clarify the use of the fold expression:

(statement | ...)

The minimal version would look something like this:

template<typename T>
unsigned long long int stuffFor();

template<typename... T>
unsigned long long int variadicFoldedStuff() 
{
    return (stuffFor<T>() | ...);
}

Upvotes: 7

Related Questions