Страницы

Поиск по вопросам

среда, 29 января 2020 г.

Объясните, пожалуйста, почему данная спецификация шаблона вызывает ошибку

#cpp #шаблоны_с++


template  const T maxN( const T* arr, const size_t length);
template<> const char* maxN( const char** arr, const size_t length);


Здесь ошибка "отсутствуют экземпляры шаблон функции, соответствующие заданному типу"

При этом, если в шаблоне имя типа сделать не константой,то спецификация без ошибки:

template   T maxN(  T* arr, const size_t length);
template<> const char* maxN( const char** arr, const size_t length);


Такой код компилятор допускает...

Вопрос в том, что не так с первым вариантом кода?
    


Ответы

Ответ 1



Вас вводят в заблуждения контринтуитивные правила для описания типов в С/C++. В общем случае они определяются спиральным правилом, которое обычно вырождается в чтение справа налево. При этом квалификаторы const и volatile применяются к тому, что стоит слева от них, за исключением ситуации, когда слева от них ничего нет. Соответственно попытка простой замены T на char * в записи const T не приведет к жалаемому результату, так как const char * будет группироваться как (const char) * (указатель на константный char), а не как const (char *) (константный указатель на char). Если аккуратно расписать исходный шаблон, всегда оставляя const справа, то такую замену можно будет провести без проблем: template T const maxN( T const * arr, size_t const length); template< > char * const maxN( char * const * arr, size_t const length);

Ответ 2



Потому что посмотрите, к чему относится const. У вас в первом шаблоне arr - указатель на константный T, а в специализации - указатель на указатель на константный char, а не на константный char*... Смотрите - вот такой код вполне проходит: template const T maxN( const T* arr, const size_t length); typedef char * pchar; template<> const pchar maxN( const pchar* arr, const size_t length);

Ответ 3



В первом варианте вы делаете специализацию главного шаблона для T == char *. Если аккуратно подставить char * вместо T, то получится template const T maxN( const T* arr, const size_t length); template<> char* const maxN( char* const* arr, const size_t length); Это будет корректной специализацией для первого варианта. У вас же в первом варианте константность в специализации "уехала" совсем не туда. Имена типовых шаблонных параметров ведут себя так же, как typedef-имена. Вы, похоже, находитесь в плену того же самого заблуждения, которое часто встречается с typedef и const typedef с константой Во втором варианты вы "решили" проблему неправильной расстановки константности методом "лучшее лекарство от перхоти - гильотина", то есть убрав квалификатор const вообще

Ответ 4



Если у вас есть: const char *p = "old_array\n"; //указатель на константный символ То указатель p записывает адрес массива, символы которых нельзя модифицировать(константные). Но зато этот указатель не константный, и можно туда записать адрес другого массива: p = "new array\n"; Теперь он указывает на другой массив. Ваш шаблон запрещает делать это(он говорит, что вы можете инстанцировать так, что обьект типа должен быть константным, а значит, если передаете указатель, то его значение нельзя менять, он всегда укажет на тот же массив или обьект), если передать в функцию этот указаель. Однако ваша специализация разрешает, потому что указатели не константные(константные лишь массивы(обьекты), и потому сигнатуры отличаются. Второй вариант не требует константного указателья...

Комментариев нет:

Отправить комментарий