9

How to specialize variadic template function that has const reference for an argument?

Example:

template<typename T, typename... Args>
T foo(Args... args) = delete;

template<> int foo(int a, const char* str, const Test& t) { .... } // Fails to compile
//template<> int foo(int a, const char* str, Test ) { .... } // Ok

int main() {

    auto i = foo<int>(10, "test string!", t);
    return 0;
}

When invoking function foo with declared const Test&argument, the compiler fails to see specialized function and fallbacks to deleted function:

 error: use of deleted function ‘T foo(Args ...) [with T = int; Args = {int, const char*, Test}]’
     auto i = foo<int>(10, "test string!", t);




The above code compiles fine if I remove const reference from argument. What am I doing wrong?

The code can be found here

Bected
  • 153
  • 7

2 Answers2

7

This is because the template arguments which the primary template deduce for your call are int, const char*, and Test, not const Test&. This means that your specialization is not used because the template arguments don't match the parameters.

Your simplest option is to provide a separate overload rather than a specialization:

template <typename T>
T foo(int a, const char* str, const Test& t) { /*...*/; } 

Live demo

TartanLlama
  • 63,752
  • 13
  • 157
  • 193
5

Automatic template deduction is not smart enough to guess that you want it to set the last template parameter to const Test& instead of Test. More exactly type deduction always remove cv qualifiers from a type.

You new explicit template instantiation here:

auto i = foo<int, int, const char *, const Test&>(10, "test string!", t);
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252