Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ static_assert 완벽 가이드: 컴파일 타임 검증부터 C++17 문법까지

static_assert는 프로그램을 컴파일하는 시점에 지정한 조건을 검사하고, 조건이 충족되지 않으면 화면에 오류 메시지를 출력하는 C++ 기능입니다. 런타임이 아니라 컴파일 타임에 동작하기 때문에 프로그램 성능에 아무런 영향을 주지 않으면서도 논리적 오류나 타입 불일치를 개발 초기 단계에서 잡아낼 수 있어 개발자에게 매우 유용한 도구입니다.

버전별 문법 차이

C++11과 C++14 시절에는 static_assert를 정의할 때 반드시 개발자가 직접 오류 메시지를 작성해 함께 전달해야 했습니다.

static_assert(조건식, "오류 메시지"); // C++11 / C++14

하지만 C++17부터는 메시지 없이 static_assert만 호출하는 것이 허용되어 훨씬 간결하게 사용할 수 있게 되었습니다.

static_assert(조건식); // C++17부터 메시지 생략 가능

또한 static_assert는 BOOST_STATIC_ASSERT처럼 기존 assert 계열 라이브러리 함수들과도 호환되어 함께 활용할 수 있습니다.

주요 특징

  • 컴파일 시점에 평가되므로 런타임 오버헤드가 전혀 없습니다.
  • 검사 조건은 반드시 상수 표현식(constant expression)이어야 합니다.
  • is_convertible 같은 타입 특성(type trait)과 결합하면 템플릿 코드의 타입 안정성을 크게 높일 수 있습니다.
  • 조건이 거짓이면 컴파일 자체가 실패하며, 미리 지정해 둔 메시지가 컴파일러 오류로 출력됩니다.

문법

static_assert(상수_표현식);
static_assert(상수_표현식, "문자열_리터럴");

첫 번째 형태는 C++17 이상에서만 사용할 수 있고, 두 번째 형태는 C++11 이상의 모든 표준에서 지원됩니다.

예제

아래 예제는 배열을 채우는 제네릭 함수 fillarray() 내부에서 static_assert를 사용해, 전달된 함수가 반환하는 타입이 배열 요소의 타입과 호환되는지 컴파일 시점에 검사합니다.

#include <bits/stdc++.h>
using namespace std;

// 템플릿 선언
template <typename T, size_t N, typename F>

// 값을 저장하는 함수
void fillarray(array<T, N>& a, F&& f) {
    // fun()이 반환하는 타입이 T와 호환되지 않으면 컴파일 오류 발생
    static_assert(is_convertible<typename result_of<F()>::type, T>::value,
                  "Incompatible type returned by fun()");
    for (auto& x : a)
        x = f();
}

int main() {
    array<vector<string>, 20> a;
    // vector<string> 대신 int를 반환하는 람다를 전달했으므로 컴파일 오류!
    fillarray(a, []() { return 42; });
    return 0;
}

여기서 is_convertible<typename result_of<F()>::type, T>는 "함수 f가 반환하는 타입이 T로 변환 가능한가?"라는 질문에 답하는 타입 특성입니다. 위 예제에서는 vector<string> 타입 배열에 int를 반환하는 람다를 전달했기 때문에 조건이 거짓이 되어 컴파일이 실패합니다.

출력 결과

prog.cpp:10:5: error: static assertion failed:
Incompatible type returned by fun()

이처럼 static_assert는 잘못된 코드가 빌드되는 것을 원천적으로 차단하며, 사전에 작성해 둔 메시지 덕분에 어느 부분이 문제인지 즉시 파악할 수 있습니다. 반대로 타입 변환이 실제로 가능한 경우(예: vector<string>을 반환하는 람다를 전달하는 경우)에는 오류 없이 정상적으로 컴파일됩니다. 템플릿 기반 라이브러리를 작성할 때 잘못된 인스턴스화를 명확한 메시지로 걸러내는 용도로 특히 유용하니, 적극적으로 활용해 보시기 바랍니다.