std :: ssize ()가 C ++ 20에 도입 된 이유는 무엇입니까?


99

C ++ 20std::ssize() 은 아래와 같이 무료 기능을 도입했습니다 .

template <class C>
    constexpr auto ssize(const C& c)
        -> std::common_type_t<std::ptrdiff_t,
                              std::make_signed_t<decltype(c.size())>>;

가능한 구현은를 사용하여 cl ass C 멤버 함수의 static_cast반환 값을 서명 된 대응 항목 으로 변환하는 것 같습니다 .size()

size()C 의 멤버 함수는 항상 음이 아닌 값을 반환 하기 때문에 서명 된 변수에 저장하려는 사람이있는 이유는 무엇입니까? 정말로 원하는 경우에는 간단 static_cast합니다.

std::ssize()C ++ 20에 도입 된 이유는 무엇 입니까?


4
@ Jarod42 정의되지 않은 대신 구현이 정의되지 않았습니까? (서명 된 오버플로는 정의되지 않았지만 서명 된 변환은 구현이 정의 됨)
phön

8
ssizeof연산자도 추가하면됩니다 .
geza

3
이것은 다소 관련이있을 수 있습니다 : stackoverflow.com/questions/30395205/…
Marco13

10
@ JohnZ.Li 너무 비합리적으로 들릴 위험이 있습니다 . 정수 유형에 관한 C ++의 전체 유형 시스템 이 망가 졌다고 생각합니다. 물론, 일부 기이 한 (예 : a char가 얼마나 많은 비트를 가지고 있는지 알지 못하는 것과 같은 ) C에서 상속되고 최소한.에 의해 어느 정도 완화 되었다고 주장 할 수 (u)intX_t있지만 여전히 똑같이 미묘 하고 중요한 버그 의 끝없는 소스입니다 . 같은 ssize것은 패치 일 뿐이며, 이것이 사람들이 엄격하게 따를 수있는 일반적인 "모범 사례 지침"에 빠질 때까지 (아마도 "영원히") 시간이 걸립니다.
Marco13

6
@ Marco13 : 반면에 C / C ++ 유형 시스템 (예 : Java의 고정 유형 시스템과 반대)은 C / C ++ 코드가 대부분의 다른 언어가 비난하는 아키텍처에서 작동 하도록 허용하는 것 외에도 유능한 강사가 중요한 정보를 얻을 수 있도록 합니다. 학생의 머리에 수업. 마찬가지로 모든 세계가 64 비트는 아닙니다. 그리고 전 세계가 8 비트 문자를 사용하는 것은 아닙니다. 이다 쉽게 죽은 이런 일에 대처, 그리고 단지 강사는이를 가르 칠 경우, 당신에게 더 나은 개발을하게 처음부터 . (그리고, 당신이 있는지 확인하기 위해 것을 알고 (u)intX_t유형은 선택 을 수행?)
DevSolar

답변:


69

근거는 이 백서에 설명되어 있습니다. 인용문 :

span이 C ++ 17에 채택되었을 때 인덱스와 크기 모두 부호있는 정수를 사용했습니다. 부분적으로 이것은 컴파일 타임에 크기가 알려지지 않은 유형을 나타 내기 위해 센티널 값으로 "-1"을 사용할 수 있도록하기위한 것입니다. 그러나 size () 함수가 부호있는 값을 반환하는 STL 컨테이너를 갖는 것은 문제가 되었기 때문에 문제를 "수정"하기 위해 P1089가 도입되었습니다. 다수의지지를 받았지만 합의에 필요한 2 대 1 마진은받지 못했습니다.

이 논문 P1227은 비 멤버 std :: ssize 및 멤버 ssize () 함수를 추가하기위한 제안이었습니다. 이들을 포함하면 특정 코드가 훨씬 더 간단 해지고 크기 계산에서 원치 않는 무 부호화를 방지 할 수 있습니다. 아이디어는 ssize ()가 std :: ssize ()를 통해 그리고 멤버 함수로 모든 컨테이너에 대해 사용 가능 해지면 P1089에 대한 저항이 감소한다는 것입니다.


30
for(int i = 0; i < container.ssize() - 1; ++i)예는 상당히 설득력
Caleth

7
@John 실제로 그들은 string :: npos와 ​​같은 일을 할 수 있고 size_t (-1)을 특수 값으로 사용할 수 있다고 생각합니다.
rubenvb

15
@ JohnZ.Li STL 크기 유형이 서명되지 않은 것은 오랫동안 실수로 간주됩니다. 이제 불행히도 그것을 개혁하기에는 너무 늦었습니다. 무료 기능을 제공하는 것이 현재 우리가 할 수있는 최선의 방법입니다.
LF

16
@LF : 회의에서 Herb Sutter였습니다 (Bjarne도이 말을했을 것입니다). 그러나 그는 약간 틀렸다. 이제 32 비트 / 64 비트 컴퓨터에서는 서명 된 크기가 더 좋을 것입니다 (그래서 그가 맞습니다). 그러나 예전에는 (16 비트 크기) 부호있는 크기가 좋지 않았습니다 (예 : 32k 바이트 배열 만 할당 할 수 있음).
geza

11
@LF : Herb가 youtube.com/watch?v=Puio5dly9N8&t=2667을 언급하는 것을 발견했습니다 . 그가 "실제로별로 나오지 않는다"고 말했을 때 그것은 오늘날 사실입니다. 그러나 20 년 이상 전에는 (16 비트 시스템) 전혀 사실이 아니 었습니다. 따라서 STL이 설계되었을 때 unsigned를 사용하는 것은 그다지 실수가 아닙니다.
geza

50

Eric Niebler에게서 무상으로 도난 당했습니다.

'Unsigned types signal that a negative index/size is not sane'STL이 처음 설계되었을 때 지배적 인 지혜였습니다. 그러나 논리적으로 많은 것들이 긍정적일 필요는 없습니다. 컬렉션에서 추가되거나 제거 된 요소의 수를 나타 내기 위해 부호있는 정수로 카운트를 유지하고 싶을 수 있습니다. 그런 다음 그것을 컬렉션의 크기와 결합하고 싶습니다. 컬렉션의 크기가 서명되지 않은 경우 이제 버그 팜인 서명 된 산술과 서명되지 않은 산술을 혼합해야합니다. 컴파일러는 이것에 대해 경고하지만 STL의 디자인은 프로그래머에게이 상황을 강요하기 때문에 경고가 너무 흔하여 대부분의 사람들이 꺼집니다. 이것은 실제 버그를 숨기기 때문에 부끄러운 일입니다.

인터페이스에서 서명되지 않은 int를 사용하는 것은 많은 사람들이 생각하는 혜택이 아닙니다. 실수로 사용자가 약간 음수를 API에 전달하면 갑자기 큰 양수가됩니다. API가 숫자를 서명 된 것으로 취했다면 숫자가 0보다 크거나 같다고 주장하여 상황을 감지 할 수 있습니다.

서명되지 않은 int의 사용을 비트 트위들 링 (예 : 마스크)으로 제한하고 서명 된 int를 다른 곳에서 사용하면 버그가 발생할 가능성이 적고 버그가 발생할 때 감지하기가 더 쉽습니다.


6
Swift는 음의 부호가 부호없는 숫자로 재 해석 될 염려가 없더라도이 접근 방식을 사용합니다 (암시 적 캐스트가 없기 때문에 처음부터이 미친 재미있는 집에 들어가게하는 것입니다). 그들은 Int(배열 인덱싱과 같이) 양수 만 의미가있는 경우에도 (머신 워드 크기) 가 정수의 일반적인 통화 유형이어야한다는 접근 방식을 취합니다 . 그것에서 벗어나는 것은 잘 근거가 있어야합니다. 모든 곳에서 캐스트에 대해 걱정할 필요가 없다는 것이 좋습니다.
Alexander-Monica 복원

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.