Lorsque vous faites appel std::sort()
à 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));
}
Gcc et clang renvoient tous deux une erreur sur le tri sur std::array
- clang dit
erreur: utilisation de l'identifiant non déclaré «tri»; vouliez-vous dire 'std :: sort'?
Changer pour std::sort(begin(foo2), end(foo2))
résoudre le problème.
MSVC compile le code ci-dessus tel qu'il est écrit.
Pourquoi la différence de traitement entre std::vector
et std::array
; et quel compilateur est correct?
sort(...
->std::sort(...
. Je suppose que l'ADL (recherche dépendante de l'argument) est ce qui vous fait trébucher. Ça, ou des guides de déduction. Dans tout les cas; qualifiez toujours les fonctions que vous appelez.std::sort
qui mène à une recherche dépendante des arguments (comme vous l'avez déjà pourstd::begin
etstd::end
)?namespace std
même là où un type de pointeur simple aurait fonctionné. Je crois que cela consiste à insérer des vérifications de build de débogage pour détecter les dépassements et autres erreurs courantes.Réponses:
Cela revient au type
begin
et auend
résultat et à la façon dont cela fonctionne avec la recherche dépendante de l'argument .Dans
vous obtenez
et depuis
std::vector<int>::iterator
est membre d'std
ADL trouvesort
dansstd
et l'appel aboutit.Avec
Vous obtenez
et parce qu'il
int*
n'est pas membre destd
, ADL ne cherchera passtd
et vous ne trouverez passtd::sort
.Cela fonctionne dans MSVC car
devient
et puisque
std::_Array_iterator
fait partie desstd
découvertes ADLsort
.Les deux compilateurs sont corrects avec ce comportement.
std::vector
etstd::array
n'ont aucune exigence sur le type utilisé pour l'itérateur, sauf qu'il satisfait à l' exigence LegacyRandomAccessIterator et en C ++ 17 pourstd::array
que le type soit également un LiteralType et en C ++ 20 qu'il soit un ConstexprIteratorla source
std::array
iterator doivent êtreint*
ou peut - il être un type de classe? De même,std::vector
il serait pertinent de se demander si l'itérateur doit être un type de classe sur lequel ADL fonctionnera, ou s'il peut l'êtreint*
également.std::iterator
, quelque chose d'autre, ou juste un pointeur.int*
pourstd::array
mais pas pourstd::vector
.std::array
et nestd::vector
sont pas spécifiés, ce qui signifie que l'implémentation est autorisée à les définir comme des pointeurs bruts (le code ne se compilera pas) ou des wrappers de type classe (le code se compilera uniquement si le type de classe astd
comme espace de noms associé ADL).std::vector<T>::iterator
est un alias.