Использование const char** с шаблонной специализацией
Я пытаюсь написать шаблонную специализацию для функции, которая возвращает максимальное значение массива числовых значений (общая версия) или самую длинную c-строку массива c-строк (специализация). Если я не использую константу, мои прототипы функций выглядят так
template <typename T>
T maxn(T* my_Tptr, unsigned int n);
template <>
char* maxn <char*> (char** my_cstrings, unsigned int n);
и мой код компилируется.
Однако, если я пытаюсь использовать константу, мои прототипы функций выглядят так,
template <typename T>
T maxn(const T* my_Tptr, unsigned int n);
template <>
char* maxn <char*> (const char** my_cstrings, unsigned int n);
мой код не компилируется, и компилятор (gcc) печатает эту ошибку:
ошибка: идентификатор шаблона 'maxn' для 'char* maxn(const char**, unsigned int)' не соответствует ни одному объявлению шаблона.
Куда я иду не так?
4 ответа
Проблема в const
Несс. Если вы посмотрите внимательно const T* my_Tptr
означает, что my_Tptr является указателем на const T. Но const char** my_Tptr
означает, что Tptr является указателем на указатель на const char. Таким образом, тип перемещается от указателя на const T к указателю на указатель на const T. Если вы сделаете это char* const* my_Tptr*
тогда это будет работать, так как тогда тип будет указателем на указатель на константный символ. Специализация указатель на const T*-> указатель на const char*
Не уверен, что за этим стоит вся логика, но если вы измените определение шаблона, чтобы сказать, что вы ожидаете указатели, которые помогут:
template <typename T>
T* maxn(const T** my_Tptr, unsigned int n);
template <>
char* maxn(const char** my_cstrings, unsigned int n);
Вы можете предоставить несколько перегрузок для char-case для решения проблемы:
#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';
}
Это хорошо компилируется:
template <>
char* maxn(char* const* my_cstrings, unsigned int n);
Он принимает указатель на указатель на символ const, как указано в базовом шаблоне.