I have a template function void foo(const T&)
. I need specialized implementations for [T = int]
and [T = const char*]
.
#include <iostream>
template<class T>
void foo(const T& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
}
template<>
void foo(const int& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
}
int main(int argc, char *argv[])
{
int i = 42;
const char *bar = "xyz";
foo(i);
foo(bar);
return 0;
}
The specialization for [T = int]
works, the output is:
void foo(const T&) [with T = int]
42
void foo(const T&) [with T = const char*]
xyz
But, it won't compile if I try to specialize for [T = const char*]
like so:
template<>
void foo(const char*& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
}
17:6: error: template-id 'foo<>' for 'void foo(const char*&)' does not match any template declaration
What has me puzzled is that it appears to correctly deduce [T = const char*]
when no specialization is present, but complains if I try to implement one.
Any ideas where I'm going wrong?
CodePudding user response:
You need a second const
template<>
void foo(const char* const& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
}
The template requires a const reference, but const char*&
is a reference to a pointer to a const char.
template<class T>
void foo(const T& arg)
Even better would be to use overloads instead of function template specialization, e.g.
template<class T>
void foo(const T& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
}
void foo(const int& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
}
void foo(const char*& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
}
CodePudding user response:
In this function template declaration
template<class T>
void foo(const T& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
}
you have a constant reference to the type T
. When the function is called like
const char *bar = "xyz";
foo(bar);
then the deduced type T
is const char *
(the type of a pointer to a string literal). You may imagine it the following way
typedef const char *T;
So the constant reference to the type T
will look like
const char * const &
Here is a demonstration program.
#include <iostream>
#include <type_traits>
template<class T>
void foo(const T& arg)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << arg << std::endl;
std::cout << std::boolalpha
<< std::is_same_v<T, const char *> << '\n';
std::cout << std::boolalpha
<< std::is_same_v<decltype( arg ), const char * const &> << '\n';
}
int main(int argc, char *argv[])
{
const char *bar = "xyz";
foo(bar);
return 0;
}
The program output is
void foo(const T &) [T = const char *]
xyz
true
true