Dzwoniąc std::sort()
na std::array
:
#include <vector>
#include <array>
#include <algorithm>
int main() {
std::vector<int> foo{4, 1, 2, 3};
sort(begin(foo), end(foo));
std::array<int, 4> foo2{4, 1, 2, 3};
sort(begin(foo2), end(foo2));
}
Zarówno gcc, jak i clang zwracają błąd podczas sortowania w opcji std::array
- mówi clang
błąd: użycie niezadeklarowanego identyfikatora „sort”; miałeś na myśli „std :: sort”?
Zmiana na std::sort(begin(foo2), end(foo2))
naprawia problem.
MSVC kompiluje powyższy kod zgodnie z opisem.
Dlaczego różnica w traktowaniu między std::vector
i std::array
; i który kompilator jest poprawny?
sort(...
->std::sort(...
. Wydaje mi się, że to ADL (wyszukiwanie zależne od argumentów) jest tym, co cię potyka. To lub przewodniki dedukcyjne. W każdym przypadku; zawsze określ funkcje, które wywołujesz.std::sort
która prowadzi do wyszukiwania zależnego od argumentów (tak jak już masz dlastd::begin
istd::end
)?namespace std
nawet tam, gdzie działałby prosty typ wskaźnika. Uważam, że ma to na celu wstawienie kontroli kompilacji debugowania w celu wykrycia przekroczeń i innych typowych błędów.Odpowiedzi:
Sprowadza się to do typu
begin
iend
wyniku oraz sposobu, w jaki działa to z Argument Dependent Lookup .W
dostajesz
a ponieważ
std::vector<int>::iterator
jest członkiemstd
ADL znalezisksort
wstd
i wywołanie się powiedzie.Z
Dostajesz
a ponieważ
int*
nie jest członkiemstd
, ADL nie zajrzystd
i nie będzie można go znaleźćstd::sort
.Działa to w MSVC, ponieważ
staje się
i ponieważ
std::_Array_iterator
jest częściąstd
znalezisk ADLsort
.Oba kompilatory są zgodne z tym zachowaniem.
std::vector
istd::array
nie ma żadnych wymagań dotyczących tego, jaki typ jest używany dla iteratora, z wyjątkiem tego, że spełnia on wymaganie LegacyRandomAccessIterator, aw C ++ 17 dlastd::array
tego typu również typ LiteralType, aw C ++ 20, że będzie to ConstexprIteratorźródło
std::array
iterator musi być,int*
czy może być typem klasy? Podobniestd::vector
byłoby istotne dla pytania, czy iterator musi być typem klasy, na którym będzie działać ADL, czy też możeint*
tak być .std::iterator
coś innego lub wskaźnik.int*
do,std::array
ale nie dostd::vector
.std::array
istd::vector
są nieokreślone, co oznacza realizację wolno definiować je jako surowych wskaźników (kod nie będzie kompilować) lub klasa typu owijarki (kod zostanie skompilowany tylko jeśli typ klasa mastd
jako związanego nazw ADL).std::vector<T>::iterator
jest pseudonimem.