Braced-init-lists и порядок вывода типов шаблонов функций

У меня есть вопрос, касающийся процедуры вывода типа параметра шаблона функции.

Возьмите этот пример:

#include <vector>
#include <sstream>
#include <string>
#include <iterator>
#include <fstream>

int main()
{
std::ifstream file("path/to/file");
std::vector<int> vec(std::istream_iterator<int>{file},{}); // <- This part
return 0;
}

Если я правильно понимаю, второй параметр выводится как тип std::istream_iterator из которых конструктор по умолчанию называется.

Соответствующий std::vector Конструктор объявлен как:

template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());

Так как первый тип параметра выводится как std::istream_iterator<int> второй параметр выводится как std::istream_iterator<int> и так и так может быть применена единая семантика инициализации. Я понятия не имею, в каком порядке происходит вывод типа. Я был бы очень признателен за информацию об этом.

Заранее спасибо!

6

Решение

Давайте использовать еще более простой пример:

template<class T>
void foo(T, T);

foo(42, {});

Вызов функции имеет два аргумента:

  • предварительное выражение типа int (целочисленный литерал)
  • приготовился-INIT-лист {}

Последний, {}может быть частью список_выражений но это не выражение сам. список_выражений определяется как инициализатора-лист. рамно-Init-листы не имеют типа.

Вывод типа шаблона выполняется для каждого параметра функции индивидуально [temp.deduct.type] / 2. [temp.deduct.call] / 1 сообщает о выводе типа для параметра функции P:

Если удалить ссылки и cv-квалификаторы из P дает
std::initializer_list<П’> для некоторых П’ и аргумент
список инициализатора, затем вместо каждого элемента выполняется удержание
из списка инициализатора, принимая П’ как параметр шаблона функции
тип и элемент инициализатора в качестве аргумента. В противном случае,
Аргумент списка инициализатора заставляет параметр считаться
не выводимый контекст.
[акцент мой]

Так в звонилке foo(42, {}); T не будет выведен из второго аргумента {}, Тем не мение, T можно вывести из первого аргумента.

В общем, мы можем вывести T из нескольких параметров функции. В этом случае выведенные типы должны точно соответствовать [temp.deduct.type] / 2. Нет проблем, если тип выводится только из одного параметра функции, но используется где-то еще (в другом параметре функции, который находится в невыгруженном контексте, в типе возврата и т. Д.). Вычисление типа может потерпеть неудачу, например когда параметр шаблона не может быть выведен из любой параметр функции и не задан явно.

После вычета T будет заменен intпроизводя сигнатуру функции, похожую на:

void foo<int>(int, int);

Эта функция может быть вызвана с двумя аргументами 42 а также {}, Последний будет выполнять инициализацию копирования списка, что приведет к инициализации значения второго параметра.

9

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector