Beim Aufrufen std::sort()
eines 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));
}
Sowohl gcc als auch clang geben einen Fehler bei der Sortierung auf dem std::array
- clang zurück
Fehler: Verwendung des nicht deklarierten Bezeichners 'sort'; meinten Sie 'std :: sort'?
Ändern, um std::sort(begin(foo2), end(foo2))
das Problem zu beheben.
MSVC kompiliert den obigen Code wie geschrieben.
Warum der Unterschied in der Behandlung zwischen std::vector
und std::array
; und welcher compiler ist richtig?
sort(...
->std::sort(...
. Ich denke, dass ADL (argumentabhängige Suche) Sie auslöst. Das oder Abzugsleitfäden. Auf jeden Fall; Qualifizieren Sie immer die Funktionen, die Sie aufrufen.std::sort
, die zu einer argumentabhängigen Suche führt (wie Sie es bereits fürstd::begin
und getan habenstd::end
)?namespace std
selbst dort definiert sind , wo ein einfacher Zeigertyp funktioniert hätte. Ich glaube, dies ist das Einfügen von Debug-Build-Prüfungen, um Überschreitungen und andere häufige Fehler zu erkennen.Antworten:
Dies hängt von dem Typ
begin
und demend
Ergebnis ab und davon, wie dies mit der argumentabhängigen Suche funktioniert .Im
du erhältst
und da
std::vector<int>::iterator
findet sich ein Mitglied vonstd
ADLsort
instd
und der Aufruf ist erfolgreich.Mit
Du erhältst
und weil
int*
kein Mitglied von iststd
, wird ADL nicht untersuchenstd
und Sie können nicht findenstd::sort
.Dies funktioniert in MSVC, weil
wird
und da
std::_Array_iterator
ist ein Teil vonstd
ADL-Fundensort
.Beide Compiler sind mit diesem Verhalten korrekt.
std::vector
undstd::array
es gibt keine Anforderung, welcher Typ für den Iterator verwendet wird, außer dass er die LegacyRandomAccessIterator- Anforderung erfüllt, und in C ++ 17 iststd::array
der Typ auch ein LiteralType und in C ++ 20 ein ConstexprIteratorquelle
std::array
Iterator hat seinint*
oder es kann ein Klassentyp sein? Ähnliches gilt fürstd::vector
wäre es auf die Frage relevant, ob der Iterator sein muss ein Klassentyp , auf dem ADL funktionieren wird, oder ob es sein kann ,int*
auch.std::iterator
, etwas anderes oder nur ein Zeiger sein.int*
für ,std::array
aber nicht fürstd::vector
.std::array
undstd::vector
nicht näher bezeichnet sind, ist die Umsetzung Sinn erlaubt , sie als roher Zeiger zu definieren (Code wird nicht kompiliert) oder Klasse-Typ - Wrapper (Code kompiliert nur dann , wenn der Klassentyp hatstd
als ADL zugehörigen Namespace).std::vector<T>::iterator
ist ein Alias.