Страницы

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

суббота, 14 декабря 2019 г.

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

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


#include

template std::ostream & fun(const T * dd)
{
  return std::cout << *dd << " T*" << '\n';
}

template std::ostream & fun(const T & dd)
{
  return std::cout << dd << " T&" <<'\n';
}

int main()
{
  int a = 5;
  int * b = new int(7);
  fun(a);
  fun(b);
  fun(const_cast(b));//в этом случае вызывается нужная функция
  return 0;
}

    


Ответы

Ответ 1



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

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

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