Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic template specialization with const reference

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

like image 891
Bected Avatar asked Mar 17 '17 09:03

Bected


2 Answers

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

like image 186
TartanLlama Avatar answered Nov 15 '22 16:11

TartanLlama


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);
like image 24
Serge Ballesta Avatar answered Nov 15 '22 16:11

Serge Ballesta