I.5: State preconditions (if any)
I.6: Prefer Expects() for expressing preconditions
이유
함수의 인자로 전달될 값들은 제약사항 (전제 조건) 이 있어야 하는 경우가 많습니다.
예시 (나쁜 예)
double sqrt(double x); // x 는 반드시 양수여야 합니다
위와 같이 제곱근을 구하는 함수가 있는데 x 가 양수여야만 계산이 가능하다고 가정한다면, C++ 의 타입 시스템만으로는 실수로 x 로 음수가 전달되는 것을 막을 수 없습니다. (참고로 unsigned double 자료형은 없습니다)
주석은 쉽게 무시되기도 합니다.
예시 (좋은 예)
double sqrt(double x) { Expects(x >= 0); /* ... */ }
이상적으로는 Expects(x >= 0) 조건 검사가 sqrt() 인터페이스 자체적으로 이루어지면 좋겠지만 템플릿을 사용해야 하기에 구현이 쉽지 않습니다.
대신 GSL 의 Expects() 를 함수 몸체에 넣으면 편리하게 전제 조건을 미리 검사할 수 있습니다.
알아두기
대부분의 멤버 함수에는 클래스 생성자에 의해 한번 생성되고 클래스 내부에서 사용될 땐 값이 변하지 않는 멤버 변수들이 있습니다. 이런 경우에는 각 멤버 함수에서 매번 조건 검사를 하실 필요는 없습니다.
예시 (좋은 예, 나쁜 예)
int area(int height, int width)
{
Expects(height > 0 && width > 0); // 가독성 좋음
if (height <= 0 || width <= 0) my_error(); // 가독성 나쁨
// ...
}
전제 조건은 주석, if 문, assert() 등 다양한 방법으로 표현할 수 있지만, 일반 코드와 구별하기 어렵고, 업데이트하기 어렵고, 도구로 활용되기 까다롭고, 상황에 따라 다르게 작동된다면 무용지물입니다. (디버그 모드에서만 문제가 검출되고 릴리즈 빌드에선 검출되지 않아도 정말로 괜찮으신가요?)
알아두기
사실 전제 조건에 대한 검사는 인터페이스 (함수 입력) 자체적으로 수행되어야 하는 것이 바람직하고, 올바른 언어 디자인으로 보고 있습니다.
C++ 표준 위원회에선 이 기능 추가에 대해 논의 중입니다.
알아두기
Expects() 는 알고리듬 중간에 조건을 확인하는 데 사용하셔도 좋습니다.
알아두기
unsigned 자료형을 사용해서 양수만 허용하도록 하지 마세요.
음수 값 대입을 막을수 없을 뿐만 아니라 (경고만 표시되며 암시적 형변환을 수행합니다) 오버플로우가 일어날 수 있습니다.
정리
1. assert() 는 디버그 모드에서만 동작합니다. GSL 의 Expects() 를 사용하세요.
2. unsigned 자료형을 사용해서 양수만 허용하도록 하지 마세요.
참고자료
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-nonnegative
'C++' 카테고리의 다른 글
[C++ Core Guidelines] I.9 템플릿으로 만든 인터페이스는 concepts 문법을 사용해서 구체화하자 (1) | 2024.07.05 |
---|---|
[C++ Core Guidelines] I.7, I.8 완료 조건을 명시하자 (0) | 2024.05.27 |
[C++ Core Guidelines] I.4 명확한 타입을 사용해서 인터페이스를 만들자 (0) | 2024.05.09 |
[C++ Core Guidelines] I.3 싱글톤은 가급적 쓰지 말자 (0) | 2024.05.04 |
[C++ 23] std::basic_string_view<CharT,Traits>::contains 사용하기 (0) | 2024.05.04 |