Niteliksiz sort () - neden std :: array üzerinde değil, std :: vector üzerinde kullanıldığında derleniyor ve hangi derleyici doğru?


11

Çağrılırken std::sort()bir on 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));
}

Hem gcc hem de clang, sıralamadaki bir hatayı döndürür std::array- clang diyor

hata: bildirilmemiş 'sort' tanımlayıcısının kullanımı; Şunu mu demek istedin 'std :: sort'?

İçin değiştirme std::sort(begin(foo2), end(foo2))sorunu düzeltmeleri.

MSVC yukarıdaki kodu yazılı olarak derler.

Neden tedavisinde arasındaki fark std::vectorve std::array; ve hangi derleyici doğrudur?


sort(...-> std::sort(.... Ben tahmin ADL (argüman bağımlı arama) sizi açma ne olduğunu. Bu veya kesinti rehberleri. Her durumda; her zaman aradığınız işlevleri nitelendirin.
Jesper Juhl

3
MSVC kütüphanesinin argüman bağımlı aramayastd::sort yol açan bazı uzmanlıkları olabilir mi (zaten ve gibi )? std::beginstd::end
Bazı programcı dostum

1
@Someprogrammerdude VC ++ 's stdlib'deki tüm kapların, namespace stdbasit bir işaretçi türünün işe yarayacağı yerlerde bile tanımlanan sınıf türü yineleyicileri kullanması basittir. Bunun taşmaları ve diğer yaygın hataları tespit etmek için hata ayıklama-yapı denetimleri eklemek olduğuna inanıyorum.
François Andrieux

Yanıtlar:


16

Bu, Argüman Bağımlı Arama ile sonuçlanan tür beginve endbunun nasıl çalıştığıyla ilgilidir .

İçinde

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

anladın

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

ve o zamandan beri std::vector<int>::iteratorüyesi olan stdADL buluntular sortiçinde stdve çağrı başarılı olur.

İle

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

Sen al

sort(int*, int*)

ve int*üyesi olmadığı için std, ADL bakmayacak stdve bulamayacaksınız std::sort.

Bu MSVC'de çalışır çünkü

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

olur

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

ve beri ADL bulgularının bir std::_Array_iteratorparçası . stdsort

Her iki derleyici de bu davranışla doğrudur. std::vectorve LegacyRandomAccessIterator gereksinimini karşılaması ve C ++ 17'de türün bir LiteralType olması ve C ++ 20'de bir ConstexprIterator olması std::arraydışında yineleyici için hangi türün kullanıldığı konusunda herhangi bir gereksiniminiz yoktur.std::array


1
Sanırım soru, MSVC'nin davranışının uygun olup olmadığıdır, yani std::arrayyineleyici olması gerekir mi int*yoksa bir sınıf türü olabilir mi? Benzer için std::vectoro yineleyici sorusunun alakalı olacaktır olmak zorunda ADL çalışmak, ya da olabilir mi tartışılacağı bir sınıf türü int*de.
ceviz

@walnut Uygulamanın olmasını istediği her şey olabilir. Bir std::iteratorşey, başka bir şey veya sadece bir işaretçi olabilir.
NathanOliver

1
Bu kütüphane uygulanmasında kullanmayı seçti Ayrıca neden acaba int*için std::arraydeğil için std::vector.
François Andrieux

1
Her ikisi için yineleyici türleri std::arrayve std::vectorbelirtilmemiş, yani uygulamanın bunları ham işaretçiler (kod derlenmeyecek) veya sınıf tipi sarmalayıcılar olarak tanımlamasına izin verilir (kod yalnızca sınıf türünün stdADL ile ilişkili bir ad alanı varsa derlenir).
aschepler

1
İşte ADL'nin bir takma adla başarısız olduğu bir demo ve burada ADL'nin iç içe bir sınıfla başarılı olduğu bir demo . Hem burada hem de daha önceki testlerimde std::vector<T>::iteratorbir takma ad.
user2357112 Monica
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.