Przewodniki dedukcji szablonów to wzorce skojarzone z klasą szablonu, które informują kompilator, jak przetłumaczyć zestaw argumentów konstruktora (i ich typów) na parametry szablonu dla klasy.
Najprostszym przykładem jest of std::vector
i jego konstruktor, który przyjmuje parę iteratorów.
template<typename Iterator>
void func(Iterator first, Iterator last)
{
vector v(first, last);
}
Kompilator musi dowiedzieć się, co vector<T>
jest T
typ będzie. Wiemy, jaka jest odpowiedź; T
powinno być typename std::iterator_traits<Iterator>::value_type
. Ale jak powiemy kompilatorowi bez konieczności wpisywania vector<typename std::iterator_traits<Iterator>::value_type>
?
Korzystasz z przewodnika po odliczeniach:
template<typename Iterator> vector(Iterator b, Iterator e) ->
vector<typename std::iterator_traits<Iterator>::value_type>;
To mówi kompilatorowi, że po wywołaniu vector
konstruktora pasującego do tego wzorca, wywnioskuje on vector
specjalizację przy użyciu kodu po prawej stronie ->
.
Potrzebujesz wskazówek, gdy dedukcja typu z argumentów nie jest oparta na typie jednego z tych argumentów. Inicjowanie a vector
z initializer_list
jawnie używa vector
's T
, więc nie potrzebuje przewodnika.
Lewa strona niekoniecznie określa faktyczny konstruktor. Sposób, w jaki to działa, polega na tym, że jeśli używasz dedukcji konstruktora szablonu na typie, pasuje ona do argumentów, które przekazujesz we wszystkich przewodnikach dedukcji (rzeczywiste konstruktory szablonu podstawowego zapewniają niejawne przewodniki). Jeśli istnieje dopasowanie, używa go do określenia, które argumenty szablonu mają dostarczyć do typu.
Ale po wykonaniu tej dedukcji, gdy kompilator ustali parametry szablonu dla typu, inicjalizacja obiektu tego typu przebiega tak, jakby nic takiego się nie stało. Oznacza to, że wybrany przewodnik dedukcji nie musi pasować do wybranego konstruktora .
Oznacza to również, że możesz używać przewodników z agregatami i inicjalizacją agregatów:
template<typename T>
struct Thingy
{
T t;
};
Thingy(const char *) -> Thingy<std::string>;
Thingy thing{"A String"};
Tak więc przewodniki dedukcji służą tylko do określenia inicjowanego typu. Rzeczywisty proces inicjalizacji przebiega dokładnie tak samo, jak wcześniej, po dokonaniu tego ustalenia.