There is a template function that takes an argument of arbitrary type. I want to make a specialization of this function for strings, but at the same time pass a string not by value, but by const reference.

For example:

#include <iostream> template<typename T> void f(T param) { std::cout << "General" << std::endl; } template<> void f(const std::string& param) { std::cout << "const std::string&" << std::endl; } void g(const std::string& str) { f(str); } int main() { std::string str; f(str); g(str); } 

In this example, unfortunately, the specialization does not work. A non-specialized function is always called.

Tell me, please, how best to make such a specialization or overload?

  • In general, it is better not to use specialization of template functions , but to use overloads, since such specializations do not participate in overload resolution - cpp questions

2 answers 2

The deduction rules for the template arguments in both f calls deduce T == std::string . Therefore, your specialization simply does not fit the deducted T value, i.e. the "main" pattern will be used. If you want to "catch" these calls in the specialization of the template, then it will have to specialize for std::string , and not for const std::string & .

You can only redirect such calls to your current specialized version "manually", i.e. explicitly specifying a template argument

 f<const std::string &>(str); 

And if you make the overload with a non-template function for const std::string & , and not a template specialization, then it is the overloaded function that will be called in both cases.

 void f(const std::string& param) { std::cout << "const std::string&" << std::endl; } 

    You can simply pass a reference to the template argument, i.e.

     template<typename T> void f(T& param) { std::cout << "General" << std::endl; } 

    Leave the rest as is