Вывод шаблона C ++ - T становится типом указателя - PullRequest
0 голосов
/ 01 мая 2020

У меня есть этот фрагмент кода

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

template <typename T>
void p(const T& value)
{
  std::cout << value << std::endl;
}

int main()
{
  int* i = new int(5);
  p(i);
}

1) Согласно https://cppinsights.io/ функции шаблона эквивалентны

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

template <typename T>
void p(const T& value)
{
  std::cout << value << std::endl;
}

/* First instantiated from: insights.cpp:18 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void p<int *>(int *const & value)
{
  std::cout.operator<<(value).operator<<(std::endl);
}
#endif 

Для меня это странно , В соответствии с «Пунктом 1 действующего современного c ++» единственный случай, когда T может быть выведен как T & (или, я думаю, T *), это когда параметр функции является универсальной ссылкой (ссылкой для пересылки). Однако этот случай T выводится как int *, а параметр, если просто указатель.

2) Если я заменю

int* i = new int(5);

на

const int* i = new int(5);

Это результат (то, что я ожидал за первое место)

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

/* First instantiated from: insights.cpp:18 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void p<int>(const int * value)
{
  std::cout.operator<<(*value).operator<<(std::endl);
}
#endif


template <typename T>
void p(const T& value)
{
  std::cout << value << std::endl;
}

3) Назад к 1), если убрать перегрузку

template <typename T>
void p(const T& value)

Так у меня только

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

int main()
{
  int* i = new int(5);
  p(i);
}

Результат -

template <typename T>
void p(const T* value)
{
  std::cout << *value << std::endl;
}

/* First instantiated from: insights.cpp:12 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void p<int>(const int * value)
{
  std::cout.operator<<(*value).operator<<(std::endl);
}
#endif


int main()
{
  int * i = new int{5};
  p(i);
}

Не могли бы вы объяснить, почему для T возможно вывести как int * в вопросе 1) int в вопросе 2)? Также я не понимаю порядок вывода аргументов шаблона 3).

Спасибо за любые подсказки / объяснения.

1 Ответ

1 голос
/ 01 мая 2020

Последовательность неявного преобразования из int * в int * const & лучше, чем последовательность неявного преобразования из int * в const int *.

Последняя содержит квалификационное преобразование , а первый - нет.

Вывод аргумента шаблона - это ответ на вопрос "какой тип я заменяю T вместо", а не "какой тип value". Для template <typename T> void p(const T* value) это должно убрать * из типа аргумента.

...