iteracyjne nad strumień wejściowy, chcielibyśmy zazwyczaj użyć std::istream_iterator
tak:Zakres oparte pętli nad strumieniem wejściowym
typedef std::istream_iterator<std::string> input_iterator;
std::ifstream file("myfile");
for (input_iterator i(file); i != input_iterator(); i++) {
// Here, *i denotes each element extracted from the file
}
Byłoby miło, gdybyśmy mogli używać zakresie oparte for
oświadczenie iteracyjne nad strumieniami wejściowymi. Jednakże, dla obiektów typu klasy zasięg oparte for
wymaga przedmiotu mieć begin()
i end()
metody (§6.5.4 pogrubienie nacisk dodano)
if
_RangeT
is an array type, begin-expr and end-expr are__range
and__range + __bound
, respectively, where__bound
is the array bound. If_RangeT
is an array of unknown size or an array of incomplete type, the program is ill-formed;if
_RangeT
is a class type, the unqualified-idsbegin
andend
are looked up in the scope of class_RangeT
as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, begin-expr and end-expr are__range.begin()
and__range.end()
, respectively;otherwise, begin-expr and end-expr are
begin(__range)
andend(__range)
, respectively, wherebegin
andend
are looked up with argument-dependent lookup (3.4.2). For the purposes of this name lookup, namespacestd
is an associated namespace.
Strumienie wejściowe nie mają tych funkcji składowych (nie są to kontenery), więc nie będzie na nich działał profil for
bazujący na zasięgach. Ma to sens w każdym razie, ponieważ potrzebowałbyś jakiegoś sposobu na określenie typu do wyodrębnienia (std::string
w powyższym przypadku).
Ale jeśli wiemy, co chcemy, aby wyodrębnić, jest to możliwe do zdefiniowania własnych begin()
i end()
funkcje (może specjalizacji lub przeciążeniem std::begin()
i std::end()
) dla strumienie wejściowe takie, że zostaną uznane przez dostępu członkiem klasy odnośnika jako opisane powyżej?
Nie jest jasne (przynajmniej dla mnie), od §6.5.4, czy funkcje będą wtedy wyszukiwane za pomocą wyszukiwania zależnego od argumentu, jeśli poprzednie wyszukiwanie zakończy się niepowodzeniem. Inną rzeczą do rozważenia jest to, że std::ios_base
i jego pochodne mają już członka o nazwie end
, który jest flagą do wyszukiwania.
Oto zamierzony rezultat:
std::ifstream file("myfile");
for (const std::string& str : file) {
// Here, str denotes each element extracted from the file
}
Lub:
std::ifstream file("myfile");
for (auto i = begin(file); i != end(file); i++) {
// Here, *i denotes each element extracted from the file
}
Czy to tylko ja, czy jest to dość niejasne ze specyfikacji? Wygląda na to, że 'std :: begin()' i 'std :: end()' zostaną znalezione tylko wtedy, gdy '_RangeT' nie ma typu tablica lub klasa. –
Tak, to nie jest najlepsze sformułowanie, ale myślę, że masz zamiar przeczytać to jako "jeśli jest to klasa I ma .begin i .end to użyje tych ... inaczej", tzn. Możesz podać darmowe funkcje . –
"*" zacząć "i" koniec "są wyszukiwane w zakresie klasy _RangeT ... i jeśli ** albo ... znajdzie co najmniej jedną deklarację **," begin-expr "i" end-expr "są '__range.begin()' i '__range.end()' * "- ponieważ' std :: ios_base :: end' istnieje (a więc 'std :: ifstream :: end' zostanie znaleziony) gra jest już dostępna . '.begin()' nie zostanie znaleziony, a '.end()' będzie błędem składni. –