Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overload variadic template's fixed parameters

Is it possible to override a variadic template by changing the number of fixed parameters before the function parameter pack? For example:

#include <iostream>

template <typename ...Args>
void foo(std::string, std::string, std::string, Args...) 
{ 
  std::cout << "THREE STRINGS\n"; 
}

template <typename ...Args>
void foo(std::string, std::string, Args...) 
{ 
  std::cout << "TWO STRINGS\n"; 
}

int main() {
  foo("key", "msg", "data", 1);
}

Running this causes the second foo to be called, but I want the first to be called. Is there a better way to overload this function?

like image 494
sma Avatar asked Feb 23 '18 13:02

sma


2 Answers

Second variant is selected because it does not involve an extra conversion required to create an instance of std::string for the last argument. If you call class constructors explicitly (or adjust arguments to take exactly what you pass) then it will work fine:

foo(std::string{"key"}, std::string{"msg"}, std::string{"data"}, 1, 2); // THREE STRINGS

online compiler

like image 191
user7860670 Avatar answered Sep 21 '22 02:09

user7860670


This is because a string literal is not of type std::string. It is of type const char[N]. So the type of the third parameter of the function instantiated from the second function template is deduced to be const char*, which is considered a better match than the function instantiated from the first function template.

You can change the type of the parameters from std::string to const char*, or use explicit conversions suggested by VTT's answer.

like image 38
xskxzr Avatar answered Sep 20 '22 02:09

xskxzr