Search code examples
c++variadic-templatesvariadic-functionsspecialization

How to specialized a variadic argument method defined inside a variadic templated class?


I have a variadic templated class which contains a method with variadic arguments. I would like to specialize the method depending on some of the parameters provided with a specialized version of the class.

I know how to specialize variadic argument functions and how to perform template specialization. Unfortunately, I have not managed to use both specializations together.

My current solution seems to be overriding the solution which is not what I want. Below is the simplified problem

    #include <iostream>

struct X;
struct Y;

template<typename ... FooTs>
struct Foo
{
public:

  template < typename... Ts >
  static int value(Ts... args){ return 0;};

};

template <>
struct Foo<X,Y>{
    static int value(int& a, int& b, float& c)
    {
        std::cout << "specialized value 3 args..." << std::endl;
        return 0;
    }
};

/* Ideally I would also like to have such specialization
template <>
struct Foo<X,Y>{
    int value(int a, int b)
    {
        std::cout << "specialized value 2 args..." << std::endl;
        return 0;
    }
};*/

int main(){
    Foo<X, Y> foo;
    int a = 1;
    int b = 2;
    float c = 3.4;
    Foo<X,Y>::value(a, b, c);
    foo.value(a, b, c);
    // foo.value(a, b);  // error: no matching function for call to 'Foo<X, Y>::value(int&, int&)
    return 0;
}

How can I achieve the specialization of the "value" method on the example above?


Solution

  • There can only be be single Foo<X,Y> type.

    Because of this, you cannot specialize Foo itself based on the template parameters of one of its functions. Think about it: What would happen if Foo had multiple templated functions inside of it?

    However, you can create a specialized version of the function like you are asking by overloading the function itself instead of the type:

    template<>
    template<>
    int Foo<X, Y>::value(int a, int b) {
        return 12;
    }
    
    int test() {
        return Foo<X,Y>::value(1,2);
    }