The problem is in the const
ness. If you look closely const T* my_Tptr
means my_Tptr is a pointer to const T. But const char** my_Tptr
means Tptr is a pointer to pointer to const char. So the type moves from pointer to const T to pointer to pointer to const T. If you make it char* const* my_Tptr*
then it will work, since then the type will be pointer to const char pointer. The specialization is pointer to const T*->pointer to const char*
Using const char** with Template Specialization
-
19-07-2023 - |
Question
I am trying to write a template specialization for a function that returns the maximum value of an array of numeric values (general version) or the longest c-string of an array of c-strings (specialization). If I do not use const-ness, my function prototypes look like this
template <typename T>
T maxn(T* my_Tptr, unsigned int n);
template <>
char* maxn <char*> (char** my_cstrings, unsigned int n);
and my code compiles.
However, if I try to use const-ness, my function prototypes look like this,
template <typename T>
T maxn(const T* my_Tptr, unsigned int n);
template <>
char* maxn <char*> (const char** my_cstrings, unsigned int n);
my code does not compile, and the compiler (gcc) prints this error:
error: template-id 'maxn' for 'char* maxn(const char**, unsigned int)' does not match any template declaration.
Where am I going wrong?
Solution
OTHER TIPS
Not sure what is the whole logic behind it but if you change your template definition to say that you are expecting pointers that will help:
template <typename T>
T* maxn(const T** my_Tptr, unsigned int n);
template <>
char* maxn(const char** my_cstrings, unsigned int n);
You might provide several overloads for the char-case to resolve the issue:
#include <iostream>
#include <stdexcept>
template <typename T>
T maxn(const T* const data, unsigned int n) {
throw std::logic_error("Failure");
}
const char* maxn(const char * const * data, unsigned int n) {
return "Success";
}
inline const char* maxn(const char** data, unsigned int n) {
return maxn(static_cast<const char * const *>(data), n);
}
inline const char* maxn(char* const * data, unsigned int n) {
return maxn(static_cast<const char * const *>(data), n);
}
inline const char* maxn(char** data, unsigned int n) {
return maxn(static_cast<const char * const *>(data), n);
}
int main() {
const char* a[] = { "A", "B", "C" };
std::cout << maxn((const char * const *)a, 3) << '\n';
std::cout << maxn((const char **)a, 3) << '\n';
std::cout << maxn((char * const *)a, 3) << '\n';
std::cout << maxn((char**)a, 3) << '\n';
}
This compiles fine:
template <>
char* maxn(char* const* my_cstrings, unsigned int n);
It accepts a pointer to a const char pointer like specified in the base template.