Search code examples
c++templatesvariadic-templatesoverload-resolutionfunction-templates

Specialization of variadic template function over the non-variadic arguments


I have a template for a function that accepts at least one parameter and performs some formatting on the rest:

template <typename T, typename... ARGS>
void foo(T first, ARGS&&... args)
{
    // ...
}

I want it to do a different thing when the first parameter is of a specific type. I like the compiler to choose this particular version, where the rest of the variadic arguments are just ignored. So I tried template specialization:

template <>
void foo(const ICON* p)
{
    // ...
}

or:

template <typename T, typename... ARGS>
void foo(const ICON* p, ARGS&&... args)
{
   // ...
}

I also tried a non-templated overload, though it always picks the first version.

The caller code is supposed not to know about templates at all (legacy code, backwards-compatibility nonsense, etc.) So it relies on type deduction and calls like this:

MyClass fooMaker;
fooMaker.set("A", "B", 3.14, 42); // v1
fooMaker.set(pIcon);              // v2 (special)

Solution

  • If you have access to or later, using if constexpr you can retain the true statement in the foo, at compile time, as follows:

    #include <type_traits> // std::is_pointer_v, std::is_same_v
    
    template <typename T, typename... ARGS>
    void foo(T first, ARGS&&... args)
    {
        if constexpr (std::is_pointer_v<T> // is pointer check
            && std::is_same_v<T, ICON*>)   // is the type is of "ICON*"
        {
            // ICON impli...
        }
        else
        {
            // other impli...
        }
    }
    

    See online demo