[C++23 새기능 소개] [[nodiscard("이유")]] 속성 강화

C++17에서 도입된 [[nodiscard]] 속성(attribute)은 함수나 타입의 반환 값을 무시하는 경우 경고를 발생시켜, 잘못된 코드나 미처 처리되지 않은 결과값을 쉽게 파악할 수 있도록 도와주는 기능이었습니다. 그러나 이전에는 단순히 반환 값을 무시하면 경고를 주는 것에 그쳤으며, 왜 값을 무시하면 안 되는지에 대한 구체적인 이유나 힌트를 제공하기는 어려웠습니다.

 

C++23에서는 이를 개선하여 [[nodiscard]] 속성에 문자열 리터럴을 인자로 전달할 수 있게 되었습니다. 이를 통해, 반환 값을 무시하면 안 되는 구체적인 이유를 개발자에게 명확히 전달할 수 있어, 코드 품질과 유지보수성이 한층 향상됩니다.

 

이번 글에서는 [[nodiscard("이유")]] 속성의 개선점과 사용 방법, 그리고 이전 버전과 비교하여 어떤 점이 좋아졌는지 알아보겠습니다.

 

[[nodiscard("이유")]]란 무엇인가요?

  • 기존 [[nodiscard]] 속성(C++17 도입): 반환 값을 무시한 경우 컴파일러 경고를 발생시켜, 중요한 반환 값을 놓치지 않도록 도와주는 속성이었습니다. 하지만 경고 메시지에서 "왜" 반환 값을 무시하면 안 되는지 설명하기 어려웠습니다.
  • C++23의 개선: 이제 [[nodiscard]] 속성에 문자열 리터럴 인자를 전달할 수 있어, 경고 메시지에 구체적인 이유나 힌트를 추가할 수 있습니다.

예를 들어, 반환 값에 리소스 해제나 메모리 정리와 같은 중요 로직이 포함되어 있다면, 단순히 "값을 무시하지 마세요"가 아니라 "이 값에는 중요한 리소스 해제가 포함되어 있습니다. 무시하면 리소스 누수가 발생합니다."와 같은 구체적인 메시지를 경고로 제공할 수 있습니다.

이전 버전에서는 어떻게 했나요?

C++17에서 [[nodiscard]]를 도입한 이후, 반환 값을 무시하면 경고가 발생하지만, 경고 메시지는 대부분 "ignored return value of function"과 같은 일반적인 형태였습니다. 구체적인 이유를 전달하기 위해서는 함수명이나 문서화에 의존해야 했습니다.

예제: 기존 [[nodiscard]] 방식(C++17/C++20)

[[nodiscard]]
int importantCalculation() {
    return 42; 
}

int main() {
    importantCalculation(); // 경고: 반환 값을 무시했음
    return 0;
}
  • 경고는 발생하지만 왜 반환 값을 사용해야 하는지에 대한 직접적인 설명은 불가능.

C++23의 [[nodiscard("이유")]] 사용 예제

[[nodiscard("반환 값을 사용하지 않으면 리소스가 해제되지 않습니다.")]]
int allocateResource() {
    // 리소스 할당 로직
    return 0; // 할당된 리소스를 식별하는 핸들 반환
}

int main() {
    allocateResource(); // 경고 시, 메시지에 "반환 값을 사용하지 않으면 리소스가 해제되지 않습니다." 표시
    return 0;
}
  • 이제 경고 메시지에 명확한 이유("반환 값을 사용하지 않으면 리소스가 해제되지 않습니다.")가 포함됩니다.
  • 개발자는 경고를 통해 왜 반환 값을 처리해야 하는지 즉시 파악할 수 있어 오류 수정이나 코드 개선이 용이합니다.

어떻게 좋아졌나요?

  • 명확한 이유 제공: 단순히 경고만 발생하는 대신, 왜 반환 값을 무시하면 안 되는지 직접적으로 전달 가능
  • 코드 유지보수성 향상: 팀원이나 향후 개발자가 코드를 볼 때 경고 메시지를 통해 함수의 반환 값 처리 필요성을 바로 이해
  • 문서화 보완: 코드 내에서 직접 경고 이유를 제시함으로써 문서화나 주석 없이도 의도를 전달

상세한 예제와 비교

이전 방식

[[nodiscard]]
int getHandle() {
    return 10;
}

int main() {
    getHandle(); // 경고 발생 (반환 값을 무시)
    // 하지만 경고 메시지만 보고 왜 이 값을 사용해야 하는지 알기 어려움
    return 0;
}

개선된 방식(C++23)

[[nodiscard("이 핸들을 사용하지 않으면 자원이 정리되지 않습니다.")]]
int getHandle() {
    return 10;
}

int main() {
    getHandle(); // 경고 시: "이 핸들을 사용하지 않으면 자원이 정리되지 않습니다."
    return 0;
}
  • 이제 경고 메시지에서 왜 사용해야 하는지 구체적으로 알 수 있어 코드 리뷰나 디버깅 과정에서 큰 도움이 됩니다.

주의 사항

  • 경고 수준 및 컴파일러 지원: [[nodiscard("이유")]]로 인한 경고 메시지 내용은 컴파일러 구현에 따라 다를 수 있습니다. 모든 컴파일러가 메시지를 동일하게 표시하지 않을 수 있습니다.
  • 사용 상황 적절성: 너무 남용하면 경고 메시지 범람, 진정한 의도를 가리는 역효과 발생 가능. 중요한 반환 값에만 신중히 적용하는 것이 좋습니다.
  • C++23 지원 여부: 이 기능은 C++23 기능이므로, 지원하는 컴파일러와 표준 라이브러리가 필요합니다.

요약

C++23에서 개선된 [[nodiscard("이유")]] 속성을 통해 반환 값을 무시했을 때 단순 경고에서 한 발 더 나아가, 해당 반환 값이 왜 중요한지 구체적으로 전달할 수 있게 되었습니다. 이를 통해 코드의 오류 수정과 유지보수 효율성, 팀 내 커뮤니케이션이 한층 향상되며, 보다 안정적이고 명확한 코드 작성이 가능합니다.

 

 

참고 자료:

반응형