Saat memanggil std::sort()
pada 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));
}
Baik gcc dan dentang mengembalikan kesalahan pada jenis di std::array
- dentang kata
error: penggunaan 'sort' pengidentifikasi yang tidak dideklarasikan; maksud Anda 'std :: sort'?
Mengubah untuk std::sort(begin(foo2), end(foo2))
memperbaiki masalah.
MSVC mengkompilasi kode di atas seperti yang tertulis.
Mengapa perbedaan perlakuan antara std::vector
dan std::array
; dan kompiler mana yang benar?
sort(...
->std::sort(...
. Saya kira ADL (lookup tergantung argumen) adalah apa yang membuat Anda tersandung. Itu, atau panduan deduksi. Bagaimanapun juga; selalu memenuhi syarat fungsi yang Anda panggil.std::sort
yang mengarah ke pencarian bergantung pada argumen (seperti yang sudah Anda miliki untukstd::begin
danstd::end
)?namespace std
bahkan di mana tipe pointer sederhana akan bekerja. Saya percaya ini adalah untuk memasukkan pemeriksaan debug-build untuk mendeteksi overruns dan kesalahan umum lainnya.Jawaban:
Ini datang ke jenis itu
begin
danend
hasil untuk dan bagaimana cara kerjanya dengan Argument Dependent Lookup .Di
Anda mendapatkan
dan karena
std::vector<int>::iterator
merupakan anggota daristd
ADL temuansort
distd
dan panggilan berhasil.Dengan
Anda mendapatkan
dan karena
int*
bukan anggotastd
, ADL tidak akan melihat ke dalamstd
dan Anda tidak dapat menemukanstd::sort
.Ini berfungsi di MSVC karena
menjadi
dan karena
std::_Array_iterator
merupakan bagian daristd
penemuan ADLsort
.Kedua kompiler benar dengan perilaku ini.
std::vector
danstd::array
tidak memiliki persyaratan apa pun jenis yang digunakan untuk iterator kecuali memenuhi persyaratan LegacyRandomAccessIterator dan di C ++ 17 untukstd::array
jenis itu juga menjadi LiteralType dan di C ++ 20 bahwa itu menjadi ConstexprIteratorsumber
std::array
iterator harus menjadiint*
atau bisa menjadi jenis kelas? Demikian pula untukstd::vector
itu akan relevan dengan pertanyaan apakah iterator harus menjadi tipe kelas di mana ADL akan bekerja, atau apakah itu bisaint*
juga.std::iterator
, sesuatu yang lain, atau hanya sebuah pointer.int*
untukstd::array
tetapi tidak untukstd::vector
.std::array
danstd::vector
tidak ditentukan, artinya implementasi diizinkan untuk mendefinisikannya sebagai pointer mentah (kode tidak akan dikompilasi) atau pembungkus tipe kelas (kode akan dikompilasi hanya jika tipe kelas memilikistd
namespace terkait ADL).std::vector<T>::iterator
adalah alias.