Использование 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, как указано в базовом шаблоне.

Другие вопросы по тегам