2014-06-10 2 views
37

는 C++ 컴파일러 (11)에 의해 완벽하게 허용 다음 코드 조각 고려 : 표준 § 따르면C++ 11에서 크기가 0 인 std :: array에 대한 이유가 있습니까?

#include <array> 
#include <iostream> 

auto main() -> int { 
    std::array<double, 0> A; 

    for(auto i : A) std::cout << i << std::endl; 

    return 0; 
} 

를 23.3.2.8 [제로 크기 배열]

1 어레이는 특수 케이스 N == 0을 지원해야합니다.

2N == 0, begin() == end() == 고유 값. 반환 값은
data()으로 지정되지 않습니다.

3 크기가 0 인 어레이의 경우 front() 또는 back()을 호출하는 것과 관련한 정의가 없습니다.

4 구성원 기능 swap()noexcept(true)과 동일한 noexcept-specification을 가져야합니다. 상기 표시된

은 제로, std::array들 예 (int A[0]; 예)들이 명시 적으로 금지되고, 또 그들이 일부 컴파일러 허용 제로 크기 어레이 (과는 대조적으로, C++ 11 완벽하게 허용 가능하다 크기 GCC)에서 정의되지 않은 동작의 비용.

이 "모순", 나는 다음과 같은 질문이 고려 :는 C++위원회 허용하기로 결정 왜

  • 가 0 std::array들 크기를?

  • 귀중한 용도가 있습니까?

+18

아마 용기와 일치하고 좀 더 일반적인 것들을 쉽게 만들 수 있습니다. – chris

+1

어떤 크기의 배열에도 어려움이있는 구현이라 할지라도'std :: array '에 부분적으로 특화되어 있어도 별 어려움이 없을 것입니다. – hvd

+2

템플릿 메타 - 프로그램은 종종 재귀 적이기 때문에, 1보다 1에서 재귀가 바닥 나는 것이 가장 간단한 경우가 많습니다. 그러나이 경우 현실적인 예제를 구성하는 데 어려움을 겪고 있습니다. – Nemo

답변

40

일반 함수가있는 경우 해당 함수가 특수 매개 변수에 대해 임의로 중단되면 잘못됩니다.

template<typename T, size_t N> 
std::array<T, N> choose(const std::vector<T> &v) { 
    ... 
} 

아무것도 어떤 이유로 N가 제로로 밝혀지면이 정의되지 않은 동작 또는 컴파일러 오류가 발생하는 경우 얻을하지 않습니다 : 예를 들어, N 임의 요소 벡터를 형성한다 템플릿 기능을 가질 수 말할 수 있습니다.

원시 배열의 경우 제한이있는 이유는 sizeof T == 0 인 유형을 원하지 않는다는 것입니다. 포인터 연산과 조합하여 이상한 결과가 발생합니다. 0 요소가있는 배열은 특별한 규칙을 추가하지 않으면 크기가 0입니다.

std::array<>은 클래스이며 항상 클래스는 >입니다. 따라서 std::array<>의 문제는 발생하지 않으며 템플릿 매개 변수를 임의로 제한하지 않고 일관된 인터페이스를 사용하는 것이 좋습니다.

4

내가 생각할 수있는 한 가지 용도는 길이가 0 인 배열의 반환이 가능하며 특별히 검사 할 기능이 있습니다.

예를 들어 std::array 기능 empty()의 설명서를 참조하십시오.

true if the array size is 0, false otherwise. 

http://www.cplusplus.com/reference/array/array/empty/

내가 예를 들어, 반환 및 STL 유형의 다른 구현을위한 표준에 부합 0 길이 배열을 확인 할 수있는 기능을 생각에는 다음과 같은 반환 값을가집니다. 벡터 및지도와 유용하므로 유용합니다.

+11

cplusplus.com을 참조하지 마십시오. 대부분의 항목이 불완전하거나 잘못되었습니다. 대신 http://en.cppreference.com/w/cpp/container/array를 사용하십시오. – kay

+4

@ 케이 그러나이 경우에는 그렇지 않습니까? 또한 불완전하거나 잘못되었을 때? –

+0

@Kay 내가 가끔 더 불분명 한 것들에 불완전하다는 것을 알지만 - 틀린가? 언제? – druckermanly

1

다른 컨테이너 클래스와 마찬가지로 사물의 배열을 나타내는 객체를 가질 수 있고 배열이 비어 있거나 비어있게 할 수있는 것이 유용합니다. 그렇게 할 수 없다면 합법적 인 방법으로 상태를 표현하기 위해 다른 객체 또는 관리 클래스를 만들어야합니다. 그 능력을 모든 컨테이너 수업에 이미 포함 시키면 매우 도움이됩니다. 그것을 사용하는 경우, 배열을 비어있을 수있는 컨테이너로 간주하고 크기 나 인덱스를 확인한 후 아무 것도 가리 키지 않을 경우 멤버를 참조하기 만하면됩니다.

1

실제로 할 수있는 경우가 꽤 있습니다. 그것은 다른 많은 언어들에도 존재합니다. 예를 들어 Java는 실제로 크기가 0 일뿐만 아니라 확장되거나 크기가 조정되거나 수정 될 수없는 목록을 반환하는 Collections.emptyList()을가집니다.

예를 들어 버스를 나타내는 클래스와 그 클래스 내의 승객 목록이있는 경우에 사용법이있을 수 있습니다. 목록은 게으른 초기화 될 수 있으며, 승객이 탑승 할 때만 생성됩니다. 누군가 getPassengers()으로 전화를 걸면 빈칸을 신고 할 때마다 새 목록을 만드는 대신 빈 목록을 반환 할 수 있습니다.

null을 반환하면 클래스의 내부 효율성을 위해 작동하지만, getPassengers()을 호출 할 때마다 결과를 확인해야하므로 클래스를 사용하는 모든 사람들이 훨씬 더 복잡해집니다. 대신 빈리스트를 얻는다면 코드가리스트가 비어 있지 않다는 가정을하지 않는 한 당신은 null을 처리하는 특별한 코드가 필요 없다.

관련 문제