Unqualified sort () - perché viene compilato se utilizzato su std :: vector e non su std :: array, e quale compilatore è corretto?


11

Quando si chiama std::sort()un 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));
}

Sia gcc che clang restituiscono un errore nell'ordinamento sul std::array- dice clang

errore: uso dell'identificatore non dichiarato 'sort'; intendevi "std :: sort"?

La modifica per std::sort(begin(foo2), end(foo2))risolvere il problema.

MSVC compila il codice sopra come scritto.

Perché la differenza di trattamento tra std::vectore std::array; e quale compilatore è corretto?


sort(...-> std::sort(.... Mi immagino che ADL (argomento di ricerca dipendente) è quello che si sta inciampare. Quello o le guide alla detrazione. In ogni caso; qualifica sempre le funzioni che chiami.
Jesper Juhl,

3
Potrebbe essere che la libreria MSVC abbia una qualche specializzazione std::sortche porta alla ricerca dipendente dall'argomento (come hai già fatto per std::begine std::end)?
Qualche programmatore amico

1
@Someprogrammerdude È semplicemente che tutti i contenitori nello stdlib di VC ++ usano iteratori di tipo di classe definiti namespace stdanche dove un semplice tipo di puntatore avrebbe funzionato. Credo che questo debba inserire controlli di debug per rilevare sovraccarichi e altri errori comuni.
François Andrieux

Risposte:


16

Questo dipende dal tipo begine dal endrisultato e dal modo in cui funziona con Ricerca dipendente dall'argomento .

In

sort(begin(foo), end(foo));

hai capito

sort(std::vector<int>::iterator, std::vector<int>::iterator)

e poiché std::vector<int>::iteratorè un membro di stdADL trova sortinstd e la chiamata riesce.

Con

sort(begin(foo2), end(foo2));

Hai capito

sort(int*, int*)

e poiché int*non è membro di std, ADL non esaminerà stde non è possibile trovare std::sort.

Questo funziona in MSVC perché

sort(begin(foo2), end(foo2));

diventa

sort(std::_Array_iterator, std::_Array_iterator)

e da allora std::_Array_iterator fa parte dei stdritrovamenti di ADL sort.

Entrambi i compilatori sono corretti con questo comportamento. std::vectore std::arraynon ha alcun requisito su quale tipo viene utilizzato per l'iteratore tranne che soddisfa il requisito LegacyRandomAccessIterator e in C ++ 17 per std::arrayquel tipo anche un tipo Literal e in C ++ 20 che è un ConstexprIterator


1
Immagino che la domanda sia se il comportamento di MSVC è conforme, vale a dire il std::array iteratore deve essere int*o può essere un tipo di classe? Allo stesso modo std::vectorsarebbe rilevante per la questione se l'iteratore debba essere un tipo di classe su cui funzionerà ADL o se può esserlo int*anche.
noce

@walnut Può essere qualunque cosa l'implementazione vuole che sia. Potrebbe essere un std::iterator, qualcos'altro o solo un puntatore.
NathanOliver

1
Mi chiedo anche perché in questa implementazione di libreria abbiano scelto di usare int*per std::arrayma non per std::vector.
François Andrieux il

1
I tipi di iteratore per entrambi std::arraye std::vectornon sono specificati, il che significa che l'implementazione può definirli come puntatori non elaborati (il codice non verrà compilato) o wrapper di tipo di classe (il codice verrà compilato solo se il tipo di classe ha stdcome spazio dei nomi associato ADL).
aschepler

1
Ecco una demo in cui l'ADL ha esito negativo con un alias ed ecco una demo in cui l'ADL ha esito positivo con una classe nidificata. Sia qui che nei miei precedenti test, std::vector<T>::iteratorè un alias.
user2357112 supporta Monica
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.