Страницы

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

вторник, 23 октября 2018 г.

Почему компилятор выбирает вариант шаблона с аргументом в виде ссылки на константу вместо указателя на константу

#include
template std::ostream & fun(const T * dd) { return std::cout << *dd << " T*" << '
'; }
template std::ostream & fun(const T & dd) { return std::cout << dd << " T&" <<'
'; }
int main() { int a = 5; int * b = new int(7); fun(a); fun(b); fun(const_cast(b));//в этом случае вызывается нужная функция return 0; }


Ответ

Потому что для вызова функции с параметром-указателем компилятору надо выполнить квалификационное преобразование int * -> const int *
А для вызова функции с параметром-ссылкой компилятору надо выполнить привязку ссылки int *const & к указателю типа int *. Обратите внимание, что, в отличие от предыдущего варианта, в данном случае квалификатор const относится к указателю int * (!), а не к указуемому типу int
Оба варианта имеют статус exact match ("полное совпадение"), но в первом случае требуется навешивание дополнительного const на тип указуемого объекта, а во втором случае тип указуемого объекта совпадает точно. Поэтому вариант со ссылкой и выбирается в процессе overload resolution.
Можно убрать из рассмотрения шаблонность (она здесь только лишний туман создает) и сократить пример до такого
void foo(const int *p) { std::cout << " T*" << '
'; }
void foo(int *const &p) { std::cout << " T&" <<'
'; }
int main() { int *b = 0; foo(b); }
Здесь тоже будет вызваться ссылочная версия по тем же самым причинам.
Более того, и ссылочность тут тоже существенной роли не играет и ситуация в моем примере может быть сведена к выбору между
void foo(const int *p); void foo(int *p);
В ситуации, когда можно вызвать функции с разными степенями cv-квалификации параметров, overload resolution выбирает наименее cv-квалифицированный вариант.

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

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