#cpp #шаблоны_с++
templateconst 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 справа, то такую замену можно будет провести без проблем: templateT 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*... Смотрите - вот такой код вполне проходит: templateconst 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, то получится templateconst 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"; Теперь он указывает на другой массив. Ваш шаблон запрещает делать это(он говорит, что вы можете инстанцировать так, что обьект типа должен быть константным, а значит, если передаете указатель, то его значение нельзя менять, он всегда укажет на тот же массив или обьект), если передать в функцию этот указаель. Однако ваша специализация разрешает, потому что указатели не константные(константные лишь массивы(обьекты), и потому сигнатуры отличаются. Второй вариант не требует константного указателья...
Комментариев нет:
Отправить комментарий