본문 바로가기

Programming/CPP11&14

[C++11] static_assert를 통한 컴파일 타임 검증

반응형

static_assert는 컴파일 타임에 소프트웨어 assertion을 위해서 추가된 문법입니다.

만약 작성된 constant-expression이 false(거짓)일 경우에 컴파일러는 메시지를 출력하고 C2338 에러를 출력합니다.

만약 true라면 아무런 영향도 발생하지 않습니다.

이미 C++에는 #error 전처리기 지시자와 assert 매크로를 통해서 assertion 처리가 가능합니다.

다만 C++의 assert는 런타임에 비교를 수행하기 때문에 성능의 하락을 가져올 수 있는 단점이 있습니다.

컴파일 타임에 해당하는 문제를 더 빨리 찾아내는 것이 모든 면에서 더 낫다고 할 수 있습니다.

#error의 경우는 컴파일 타임에 처리가 가능합니다.

다만 템플릿이 구체화되기 전에 수행되버리기 때문에 템플릿에 적용하기 부적절합니다.

이러한 문제들을 해결하기 위해서 탄생한 문법이 바로 static_assert입니다.

static_assert는 다음과 같은 형식으로 사용이 가능합니다.

static_assert( 
    constant-expression, 
    string-literal 
);

constant-expression은 bool 형식으로 변환이 되는 식이어야 합니다.

constant-expression이 true면 static_assert는 아무런 효과가 발생되지 않습니다.

조건이 false일 때, 컴파일러가 string-literal 메시지를 표시합니다.

static_assert는 템플릿도 constant-expression의 범주에 들어가기 때문에 템플릿을 디버깅하기가 용이합니다.

다음과 같은 형식으로 확인할 수 있습니다.

#include <type_traits>

template <class T>
void Func(T& a)
{
	static_assert(std::is_copy_constructible<T>::value, "Copy constructor is not available");
}

struct no_copy
{
	no_copy() = default;
	no_copy(no_copy& a) = delete;
};

int main()
{
	no_copy a;
	Func(a);
}

no_copy는 복사 생성자를 명시적으로 삭제한 클래스입니다.

no_copy의 객체를 생성해서 Func() 함수에 전달했습니다.

함수 안의 static_assert에 std::is_copy_constructible<T>::value라는 조건이 보입니다.

C++11에 추가된 것으로 복사 생성자를 통한 생성이 가능한가를 알아볼 수 있는 함수입니다.

no_copy 타입은 복사 생성자가 없기 때문에 false(0)을 리턴하며 뒤의 문장을 컴파일러가 출력합니다.

런타임에 에러를 처리하는 것보다 컴파일 타임에 처리하는 것이 더 깔끔하고 보기 좋을 수 있습니다.

또한 static_assert는 템플릿을 지원하기 때문에 템플릿의 에러도 잡아낼 수 있습니다.

static_assert는 런타임에 주는 부하가 없기 때문에 자주 사용해서 오류를 최소화하는 코드를 작성할 수 있습니다.

반응형