Ao chamar std::sort()
um 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));
}
O gcc e o clang retornam um erro na classificação no std::array
- clang diz
erro: uso do identificador não declarado 'sort'; você quis dizer 'std :: sort'?
Alterando para std::sort(begin(foo2), end(foo2))
corrigir o problema.
MSVC compila o código acima conforme escrito.
Por que a diferença de tratamento entre std::vector
e std::array
; e qual compilador está correto?
sort(...
->std::sort(...
. Eu acho que a ADL (pesquisa dependente de argumento) é o que está atrapalhando você. Isso, ou guias de dedução. Em qualquer caso; sempre qualifique as funções que você chama.std::sort
que leva à pesquisa dependente de argumento (como você já possuistd::begin
estd::end
)?namespace std
mesmo onde um tipo simples de ponteiro teria funcionado. Eu acredito que isso é para inserir verificações de depuração para detectar excedentes e outros erros comuns.Respostas:
Isto é se resume ao tipo que
begin
eend
resultado de e como isso funciona com Argumento Dependente Lookup .No
você recebe
e uma vez que
std::vector<int>::iterator
é membro destd
achados ADLsort
emstd
e a chamada tiver êxito.Com
Você recebe
e como
int*
não é membrostd
, a ADL não analisarástd
e você não poderá encontrarstd::sort
.Isso funciona no MSVC porque
torna-se
e uma vez que
std::_Array_iterator
faz parte dosstd
achados da ADLsort
.Ambos os compiladores estão corretos com esse comportamento.
std::vector
estd::array
não tem nenhum requisito sobre qual tipo é usado para o iterador, exceto que satisfaz o requisito LegacyRandomAccessIterator e no C ++ 17, parastd::array
que o tipo também seja um LiteralType e no C ++ 20 seja um ConstexprIteratorfonte
std::array
iterador precisa serint*
ou pode ser do tipo classe? Da mesma formastd::vector
, seria relevante para a pergunta se o iterador deve ser um tipo de classe no qual a ADL funcionará ou se pode serint*
também.std::iterator
, algo mais, ou apenas um ponteiro.int*
para,std::array
mas não parastd::vector
.std::array
estd::vector
não é especificado, o que significa que a implementação pode defini-los como ponteiros brutos (o código não será compilado) ou wrappers do tipo de classe (o código será compilado apenas se o tipo de classe tiverstd
um espaço de nomes associado ao ADL).std::vector<T>::iterator
é um alias.