Search code examples
c++templatesvariadic-templates

Applying a function to all template parameters


I'm trying to make a function that finds an element by id and deletes it from static vectors in some types.

template<typename First>
void RemoveComponentByID(EntityID ID)
{
    auto element = binary_find(First::Array.begin(), First::Array.end(), ID);
    First::Array.erase(element);
}

template<typename First, typename... Rest>
void RemoveComponentByID(EntityID ID)
{
    auto element = binary_find(First::Array.begin(), First::Array.end(), ID);
    First::Array.erase(element);
    RemoveComponentByID<Rest...>(ID);
}

But when I call the function RemoveComponentByID<Vector3s,Textures>(id); The error " 'RemoveComponentByID' : ambiguous function call to overloaded function" pops up. Why is that?


Solution

  • For overload resolution, there is a tie breaker between

    • template <typename T> void foo(T);
    • template <typename T, typename ...Ts> void foo(T, Ts...);

    in favour to the non variadic, but it is not the cas when those template are not part of function argument as you.

    So, neither of

    • template <typename T> void bar();
    • template <typename T, typename ...Ts> void bar();

    is more specialized, thus the ambiguous call for bar<SomeType>().

    You might do (C++17):

    template<typename First, typename... Rest>
    void RemoveComponentByID(EntityID ID)
    {
        auto element = binary_find(First::Array.begin(), First::Array.end(), ID);
        First::Array.erase(element);
        if constexpr (sizeof...(Rest) > 0) {
            RemoveComponentByID<Rest...>(ID);
        }
    }
    

    or, without recursion:

    template<typename T>
    void RemoveComponentByIDImpl(EntityID ID)
    {
        auto element = binary_find(T::Array.begin(), T::Array.end(), ID);
        T::Array.erase(element);
    }
    
    template<typename... Ts>
    void RemoveComponentByID(EntityID ID)
    {
        (RemoveComponentByIDImpl<Ts>(ID), ...);
    }