修飾されていないsort()— std :: arrayではなくstd :: vectorで使用するとコンパイルされるのはなぜですか、どのコンパイラが正しいのですか?


11

呼び出すときstd::sort()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));
}

gccとclangの両方で、並べ替えのエラーが返されますstd::array-clang

エラー:宣言されていない識別子 'sort'の使用; 「std :: sort」という意味ですか?

std::sort(begin(foo2), end(foo2))問題を修正するための変更。

MSVCは、上記のコードを記述どおりにコンパイルします。

なぜ治療の違いの間std::vectorstd::array、どのコンパイラが正しいですか?


sort(...-> std::sort(...。私は推測する ADL(引数依存ルックアップが)あなたをトリップ何であること。それ、または控除ガイド。とにかく; 呼び出す関数は常に修飾してください。
Jesper Juhl

3
MSVCライブラリに特別な特殊化がstd::sortあるため、引数に依存したルックアップが発生する可能性があります(すでにfor std::beginとのようにstd::end)。
一部のプログラマー、

1
@Someprogrammerdude VC ++のstdlib内のすべてのコンテナーnamespace stdが、単純なポインター型が機能する場所でも定義されたクラス型イテレーターを使用するだけです。これは、デバッグビルドチェックを挿入してオーバーランやその他の一般的なエラーを検出することだと思います。
フランソワアンドリュー

回答:


16

これは、 beginend引数依存型ルックアップでとその結果、およびそれがどのように機能するかによります。

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

あなたは得る

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

std::vector<int>::iteratorメンバーなのでstdADLのsortstd、コールは成功します。

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

あなたが得る

sort(int*, int*)

int*メンバーではないためstdはの、ADLは調べstdず、見つけることができませんstd::sort

これはMSVCで機能します。

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

なる

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

std::_Array_iterator一部であるためstd ADLの見つけるsort

どちらのコンパイラーもこの動作で正しく動作します。 std::vectorそしてstd::arrayそれを満たすことを除いて、イテレータのために使用されている種類にどのような要件はありませんLegacyRandomAccessIteratorの要件およびC ++ 17で用std::arrayタイプもあることLiteralTypeそれがあることとC ++ 20でConstexprIteratorを


1
私は、すなわちん、質問はMSVCの行動が適合しているかどうかだと思いstd::arrayイテレータを持っていることint*や、それがクラス型になることができますか?同様にstd::vector、イテレータ ADLが機能するクラス型である必要があるのか、それともそうであるのかという問題にも関係しint*ます。
クルミ

@walnutこれは、実装が望むとおりのものにすることができます。それはstd::iterator、他の何か、または単なるポインタである可能性があります。
NathanOliver

1
このライブラリの実装では、彼らが使用することを選んだ理由私も不思議int*のためstd::arrayではなく、ためにstd::vector
フランソワアンドリュー

1
両方のイテレータタイプ std::arraystd::vector実装は生のポインタとして、それらを定義することが許可されている(コードがコンパイルされません)またはクラス型のラッパー(コードは、クラス型が持っている場合にのみコンパイルされますつまり指定されていない、std名前空間に関連するADLとして)。
アッシェプラー

1
ここではデモだ ADLは、別名に失敗し、ここでデモだ ADLは、ネストされたクラスに成功します。ここでも、以前のテストでも、std::vector<T>::iteratorはエイリアスです。
user2357112は
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.