규정되지 않은 sort () — std :: array가 아닌 std :: vector에서 사용될 때 컴파일되는 이유는 무엇입니까?


11

호출 할 때 std::sort()A의 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와 그 소리 복귀상의 종류에 오류가 두 std::array- 그 소리가 말한다

오류 : 선언되지 않은 식별자 '정렬'사용; 'std :: sort'를 의미 했습니까?

std::sort(begin(foo2), end(foo2))문제 를 해결하기 위해 변경 .

MSVC는 작성된대로 위의 코드를 컴파일합니다.

std::vector와 사이의 치료 차이가 왜 std::array; 어떤 컴파일러가 맞습니까?


sort(...-> std::sort(.... 나는 생각 ADL (인수 종속 조회가) 당신을 트립 무슨이다. 또는 추론 가이드. 어쨌든; 항상 호출하는 기능을 검증하십시오.
Jesper Juhl

3
MSVC 라이브러리의 일부 전문성을 가지고있을 수 std::sort에 그 리드 인수 종속적 조회를 (이미에 대해 가지고있는 것처럼 std::begin하고 std::end)?
일부 프로그래머 친구

1
@Someprogrammerdude 단순히 VC ++의 stdlib에있는 모든 컨테이너 namespace std가 단순한 포인터 유형이 작동하는 경우에도 정의 된 클래스 유형 반복자를 사용 하는 것입니다. 오버런 및 기타 일반적인 오류를 감지하기 위해 디버그 빌드 검사를 삽입하는 것입니다.
François Andrieux

답변:


16

이것은 Argument Dependent Lookup 과 함께 작동하는 유형 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*의 멤버가 아니기 때문에 stdADL은 조사 std하지 않으며 찾을 수 없습니다 std::sort.

이것은 MSVC에서 작동하기 때문에

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

된다

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

그리고 ADL 찾기의 std::_Array_iterator일부 이기 때문에 . stdsort

이 동작은 두 컴파일러 모두 정확합니다. std::vectorstd::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.
François Andrieux

1
모두의 반복자 유형 std::arraystd::vector지정하고, 이행을 의미하는 원시 포인터로 정의 할 수있다 (코드는 컴파일되지 않습니다) 또는 클래스 형 래퍼 (코드는 클래스 유형이있는 경우에만 컴파일 stdADL 관련 네임 스페이스로).
aschepler

1
다음 은 ADL이 별칭으로 실패 하는 데모 이고, ADL이 중첩 클래스로 성공 하는 데모 입니다. 여기와 이전 테스트에서 모두 std::vector<T>::iterator별명입니다.
user2357112는
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.