Руководства по выводу шаблонов - это шаблоны, связанные с классом шаблона, которые сообщают компилятору, как преобразовать набор аргументов конструктора (и их типы) в параметры шаблона для класса.
Самый простой пример - это конструктор of std::vector
и его конструктор, который принимает пару итераторов.
template<typename Iterator>
void func(Iterator first, Iterator last)
{
vector v(first, last);
}
Компилятор должен понять, что vector<T>
«s T
типа будет. Мы знаем ответ; T
должно быть typename std::iterator_traits<Iterator>::value_type
. Но как сообщить компилятору, не набирая текст vector<typename std::iterator_traits<Iterator>::value_type>
?
Вы используете руководство по дедукции:
template<typename Iterator> vector(Iterator b, Iterator e) ->
vector<typename std::iterator_traits<Iterator>::value_type>;
Это сообщает компилятору, что, когда вы вызываете vector
конструктор, соответствующий этому шаблону, он будет определять vector
специализацию, используя код справа от ->
.
Руководства нужны, когда вывод типа из аргументов не основан на типе одного из этих аргументов. Инициализация a vector
из initializer_list
явно использует vector
's T
, поэтому руководство не требуется.
Левая сторона не обязательно указывает фактический конструктор. Это работает следующим образом: если вы используете вывод конструктора шаблона для типа, он соответствует аргументам, которые вы передаете всем руководствам по выводам (фактические конструкторы основного шаблона предоставляют неявные руководства). Если есть совпадение, он использует это, чтобы определить, какие аргументы шаблона предоставить типу.
Но как только этот вывод сделан, когда компилятор определит параметры шаблона для типа, инициализация объекта этого типа продолжается, как если бы ничего из этого не произошло. То есть, выбранный метод вывода не обязательно должен соответствовать выбранному конструктору .
Это также означает, что вы можете использовать руководства с агрегатами и агрегатной инициализацией:
template<typename T>
struct Thingy
{
T t;
};
Thingy(const char *) -> Thingy<std::string>;
Thingy thing{"A String"};
Таким образом, руководства по дедукции используются только для определения инициализируемого типа. Фактический процесс инициализации работает точно так же, как и раньше, после того, как это определение было сделано.