Al llamar std::sort()
a 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));
}
Tanto gcc como clang devuelven un error en el tipo en el std::array
- dice clang
error: uso del identificador no declarado 'sort'; ¿quiso decir 'std :: sort'?
Cambiar para std::sort(begin(foo2), end(foo2))
solucionar el problema.
MSVC compila el código anterior como está escrito.
¿Por qué la diferencia en el tratamiento entre std::vector
y std::array
; y que compilador es correcto?
sort(...
->std::sort(...
. Yo supongo que la ADL (dependiente de búsqueda argumento) es lo que te tropezar. Eso, o guías de deducción. En todo caso; Siempre califique las funciones que llama.std::sort
que conduzca a una búsqueda dependiente de argumentos (como ya tiene parastd::begin
ystd::end
)?namespace std
incluso donde un tipo de puntero simple hubiera funcionado. Creo que esto es para insertar verificaciones de compilación de depuración para detectar desbordamientos y otros errores comunes.Respuestas:
Esto se reduce al tipo
begin
yend
resultado y cómo funciona con la búsqueda dependiente de argumentos .En
usted obtiene
y puesto que
std::vector<int>::iterator
es un miembro de losstd
hallazgos de ADLsort
enstd
y la llamada se realiza correctamente.Con
Usted obtiene
y porque
int*
no es miembro destd
ADL, no investigarástd
y no podrá encontrarlostd::sort
.Esto funciona en MSVC porque
se convierte
y como
std::_Array_iterator
es parte destd
ADL encuentrasort
.Ambos compiladores son correctos con este comportamiento.
std::vector
ystd::array
no tiene ningún requisito sobre qué tipo se usa para el iterador, excepto que cumple con el requisito de LegacyRandomAccessIterator y en C ++ 17 parastd::array
ese tipo también es LiteralType y en C ++ 20 que es ConstexprIteratorfuente
std::array
iterador tiene que serint*
o puede ser un tipo de clase? Del mismo modostd::vector
, sería relevante para la pregunta de si el iterador tiene que ser un tipo de clase en el que funcionará ADL, o si también puede serloint*
.std::iterator
, algo más, o simplemente un puntero.int*
parastd::array
pero no parastd::vector
.std::array
ystd::vector
no están especificados, lo que significa que la implementación puede definirlos como punteros sin formato (el código no se compilará) o envoltorios de tipo de clase (el código se compilará solo si el tipo de clase tienestd
un espacio de nombres asociado a ADL).std::vector<T>::iterator
es un alias.