Czym są przewodniki po odliczaniu szablonów i kiedy powinniśmy ich używać?

87

Standard C ++ 17 wprowadza „przewodniki po odliczaniu szablonów”. Rozumiem, że mają one coś wspólnego z nową dedukcją argumentów szablonu dla konstruktorów wprowadzoną w tej wersji standardu, ale nie widziałem jeszcze prostego wyjaśnienia w stylu FAQ, czym one są i do czego służą.

  • Jakie są przewodniki po odliczaniu szablonów w C ++ 17?

  • Dlaczego (i kiedy) ich potrzebujemy?

  • Jak je zgłosić?

Tristan Pręgowany
źródło
W szczególności chciałbym wiedzieć, czy w C ++ 17 STL są faktycznie dostarczane jakieś wskazówki dotyczące dedukcji (np. Dla std :: pair lub std :: tuple). Jaka jest pełna lista standardowych typów szablonów „dedukowalnych” w C ++ 17?
Quuxplusone,
Chciałbym wiedzieć, czy jakiś kompilator to obsługuje. Próbowałem gcc, clang i vc ++. rextester.com/DHPHC32332 Nieważne, stwierdziłem, że działa tylko z gc ++ 8.1 C ++ 17 i 2a g ++ -std = c ++ 17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Jean-Simon Brochu

Odpowiedzi:

98

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::vectori 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 Ttyp będzie. Wiemy, jaka jest odpowiedź; Tpowinno 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 vectorkonstruktora pasującego do tego wzorca, wywnioskuje on vectorspecjalizację 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 vectorz initializer_listjawnie 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"}; //thing.t is a `std::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.

Nicol Bolas
źródło
7
Hmm, właśnie przyszło mi do głowy, że nawet z przewodnikiem vector v{first, last};nie zrobi dobrze :(
TC
3
@TC… chyba że właściwą rzeczą jest tworzenie wektora iteratorów. I std::string{32,'*'}[0] == ' '(dla ASCII). Ale to wszystko jest prawdą od czasu C ++ 11.
Arne Vogel,
2
co dzieje się z parametrem wektora alokatora? co by się stało, gdyby parametr wektora alokatora nie miał argumentu domyślnego? (nie można tego wywnioskować z
InputIterator
@NicolBolas: Czy mógłbyś wyjaśnić szczegóły tego, jak niejawne i jawne przewodniki dedukcji mogą działać w kontekście częściowo lub w pełni wyspecjalizowanych klas (których konstruktorzy najwyraźniej nie muszą mieć typów parametrów pasujących do tych z szablonu podstawowego)? Trudno jest znaleźć informacje na ten temat poprzez szybkie wyszukiwanie.
user541686
1
@NicolBolas: Rozumiem. Nie jest dla mnie jasne, czy w ogóle chodzi o wyraźne przewodniki po dedukcji ... Myślę, że pomocne jest włączenie tego, co dosłownie napisałeś w tym komentarzu.
user541686