2017-04-07 16 views
18

Klasa szablonu std::iterator jest ustawiona na przestarzałą w C++ 17. Dlaczego tak? Był to przydatny sposób, aby upewnić się, że działa std::iterator_traits, szczególnie jeśli można użyć domyślnych argumentów szablonu. Czy jest jakiś inny sposób robienia tego w C++ 17?Dlaczego std :: iterator jest przestarzały?

+1

Tak, jest przydatny sposób robienia tego samego w C++ 17: po prostu robisz to samo. "Przestarzałe" oznacza ** tylko **, że ** może ** odejść w przyszłości. Nie oznacza to, że nie możesz z niego korzystać, lub że nie zrobi tego, co zawsze. –

+0

@PeteBecker: Ale pytanie brzmi, jeśli program jest przestarzały, dlaczego programiści używają go, gdy * może * odejść w następnej wersji? Dlaczego na początku jest przestarzała, jeśli była tak przydatna? – Nawaz

+0

@Nawaz - to dostaje pytanie do tyłu. Jeśli jest w standardzie, dlaczego go nie używałeś? ** Wszystko ** w standardzie może, potencjalnie, odejść w przyszłości. Tak, coś, co jest przestarzałe, może z większym prawdopodobieństwem odejść, a może nie; rozważ nagłówki C, które są przestarzałe w C++, ale, z praktycznego punktu widzenia, nigdy nie znikną. –

Odpowiedz

16

Od the proposal that suggested its deprecation:

Jako pomoc w pisaniu klas iteratorów, oryginalna biblioteka standardowa dostarczana szablon klasy iterator zautomatyzować deklarację pięciu typedefs oczekiwanych każdego iteratora przez iterator_traits. Zostało to wykorzystane w samej biblioteki, na przykład w opisie std::ostream_iterator:

template <class T, class charT = char, class traits = char_traits<charT> > 
class ostream_iterator: 
    public iterator<output_iterator_tag, void, void, void, void>; 

Długa sekwencja void argumentów jest mniej oczywiste dla czytelnika, nie tylko zapewnia oczekiwane typedefs w samej definicji klasy, który jest podejściem przyjętym w bieżącym roboczym projekcie, zgodnie z wzorcem ustawionym w C++ 14, w którym wycofaliśmy wyprowadzenie z biblioteki funktorów z unary_function i binary_function.

Oprócz mniejszej jasności szablon iteratora stanowi także pułapkę dla nieostrożnych, ponieważ w typowym użyciu będzie to zależna klasa bazowa, co oznacza, że ​​nie będzie się w nią zaglądać podczas wyszukiwania nazwiska z klasy lub jego funkcje członkowskie. Prowadzi to do zaskoczonych użytkowników próbując zrozumieć, dlaczego następujący prosty zwyczaj nie działa:

#include <iterator> 

template <typename T> 
struct MyIterator : std::iterator<std::random_access_iterator_tag, T> { 
    value_type data; // Error: value_type is not found by name lookup 

    // ... implementations details elided ... 
}; 

Powodem jasności sam był wystarczający, aby przekonać lwg aktualizacji specyfikacji standardowej biblioteki do nie dłuższym mandatu standardowe adapators iteracyjnej jak pochodzące z std::iterator, więc nie ma już zastosowania tego szablonu w samym standardzie. Dlatego wygląda na silnego kandydata do deprecjacji.

Możesz również zobaczyć rozumowanie STL w LWG 2438. (H/t T.C.)


chodzi o jakiś inny sposób to zrobić, nie bardzo. Możesz w zasadzie zaimplementować własną wersję std::iterator (która nie jest zbyt trudna) lub ręcznie wypisać wszystkie te typedefs (co nie jest zbyt trudne, a ja naprawdę wolę to dla jasności).

+2

Argument STL w [LWG 2438] (https://timsong-cpp.github.io/lwg-issues/2438) również wydaje się być dobry: nazwa może wprowadzać użytkowników w błąd (zwłaszcza z * ahem * niektórych innych języków programowania) do myślenia, że ​​wyprowadzenie jest obowiązkowe, lub że pisanie funkcji akceptującej 'std :: iterator' ma sens. –

Powiązane problemy