Używanie aliasu szablonu zamiast szablonu

Jan 09 2021

Czytając książkę Wycieczka po C ++ (drugie wydanie), 2018 , nie rozumiem wyjaśnienia dotyczącego szablonów (wyjaśnię poniżej).

Dla find_allfunkcji, która zwraca a vectorz iterators do wszystkich wystąpień danej wartości w danej, podane są dwa podpisy funkcji container.

# 1:

template<typename C, typename V>
vector<typename C::iterator> find_all(C& c, V v);

# 2:

template<typename T>
using Iterator = typename T::iterator;
template<typename C, typename V>
vector<Iterator<C>> find_all(C& c, V v) ;

Oba mogą być używane w następujący sposób:

string m {"Mary had a little lamb"};
for (auto p : find_all(m,'a')) // here p is a string::iterator
    cout << *p << endl; // spoiler alert : this will print 'a's

Mówi się, że numer 2 używający aliasu szablonu

ukryj szczegóły implementacji, wprowadzając alias typu dla Iteratora

przez autora.

Chociaż wydaje mi się, że rozumiem oba sposoby korzystania z szablonów, nie rozumiem, dlaczego # 2 miałby „ukrywać szczegóły implementacji” i dlaczego jest to preferowane… Czy ktoś może mi wyjaśnić?

Dzięki !

postscriptum : Nie podałem postu z definicją funkcji (taka sama dla obu podpisów), ponieważ uważam, że nie jest to przydatne, ale dodam ją, jeśli ktoś tego potrzebuje.

Odpowiedzi

6 NathanOliver Jan 09 2021 at 05:54

Powiedzmy, że masz bazę kodu, taką jak

template<typename C, typename V>
vector<typename C::iterator> first(C& c, V v);
template<typename C, typename V>
vector<typename C::iterator> second(C& c, V v);
template<typename C, typename V>
vector<typename C::iterator> third(C& c, V v);
template<typename C, typename V>
vector<typename C::iterator> fourth(C& c, V v);
...

Jeśli zdecydujesz, że chcesz zmienić, aby zwrócić wektor const_iteratorzamiast iterator, musisz zmienić wszystkie te funkcje. Podczas używania

template<typename T>
using Iterator = typename T::iterator;
template<typename C, typename V>
vector<Iterator<C>>  first(C& c, V v);
template<typename C, typename V>
vector<Iterator<C>>  second(C& c, V v);
template<typename C, typename V>
vector<Iterator<C>>  third(C& c, V v);
template<typename C, typename V>
vector<Iterator<C>>  fourth(C& c, V v);

wszystko, co musiałbyś zrobić, to zmienić

template<typename T>
using Iterator = typename T::iterator;

do

template<typename T>
using Iterator = typename T::const_iterator;

i jesteś skończony. W ten sposób „ukrywa szczegóły implementacji”.