C++ 에는 대상을 상수화하는 2개의 키워드가 있다.

const와 constexpr이다.

 

두 키워드는 대상을 상수화한다는 공통점을 가지고 있지만 const는 대상이 초기화만 되어 있다면 그 값을 컴파일타임에 평가할 수 없어도 되지만, constexpr은 그 값을 반드시 컴파일 타임에 평가할 수 있어야 한다는 차이점이 있다.  

int B = 5;

const int A_1 = 5; //오류 안남
const int A_2 = B; //오류 안남

constexpr int C_1 = B; //오류 발생
constexpr int C_2 = 5; //오류 안남

간단히 코드로 보자면 위와 같다.

constexpr은 컴파일 타임에 정확히 판단하고 평가할 수 있는 값으로만 상수화를 허용하는 키워드인 것이다.

 

그렇다면, if constexpr은 뭘까? 

이 키워드는 조건식의 결과에 따라 코드블록을 컴파일에 포함하느냐 포함하지 않느냐를 결정하는 식이다.

 

예를 들어, 아래의 코드를 보자.

class A
{
};

template <typename T>
void Function()
{
    //작업
    
    if(T가 클래스 A의 파생 클래스라면)
    {
        //추가 작업
    }
}

이렇게 템플릿 함수에서 템플릿 인자의 자료형에 따라 추가적인 처리를 하고 싶은 상황이 있을 수도 있을 것이다.

이를 어떻게 할 수 있을까?

 

먼저, 아래와 같이 할 수 있을 것이다.

class A
{
};

template <typename T>
void Function()
{
    //작업
    
    if(std::is_base_of_v<A, T> == true)
    {
        //추가 작업
    }
}

 

std::is_base_of_v 는 첫번째 파라미터가 두 번째 파라미터의 상위 클래스라면 true를 반환하는 함수이다.

이 함수를 활용하여 위와 같이 코드를 작성하면 특정 자료형에 대해서만 추가적인 작업을 수행하도록 할 수 있다.

 

하지만, 이런 코드는 다소 비효율적일 수 있다. is_base_of_v의 결과값이 컴파일 타임에 정해지기 때문에 위의 조건식으로 인한 연산 낭비는 거의 없다고 봐도 되지만, 템플릿 함수의 코드는 줄일 수 있다면 그 양을 줄이는 것이 좋다. 왜냐하면, 템플릿이 인스턴스화 되는 과정에서 복사되는 코드의 양이 많아지면 프로그램이 비대해질 수 있기 때문이다.

 

이럴 때 사용할 수 있는 것이 if constexpr이다. if constexpr은 조건식의 결과에 따라 코드 자체를 컴파일에서 제외하는 역할을 한다. 즉, 템플릿이 다양한 자료형에 대해 인스턴스화 되는 과정에서 조건식의 값이 false로 평가되는 자료형에 대해서는 조건식이 아예 사라진 상태로 컴파일이 되는 것이다. 

 

위에서 constexpr과 const를 언급하면서, constexpr은 컴파일타임에 그 값이 평가되어야만 한다고 설명하였다. 이와 동일하게 if constexpr또한 조건식의 결과를 컴파일 타임에 평가할 수 있어야 한다.

(당연하게도 컴파일 타임에 해당 코드블록을 제외할지 말지 결정하려면 조건식의 결과를 알아야 하니..)

 

이런 이유로 if constexpr은 주로 템플릿과 함께 사용되며, 조건식에 사용할 수 있는 대상이 한정되어 있다.

(위에서 언급한 std::is_base_of와 같은 SFINAE함수, constexpr로 선언된 변수 등 컴파일 타임에 평가할 수 있는 값들..)

 

하나 TMI를 추가하자면, 템플릿 함수는 아래와 같이 사용할 수 있다.

template<int _Value>
void Test()
{
    if(_Value > 0)
    {
        std::cout << "Positive";
    }
}

int main()
{
    Test<5>();
    return 0;
}

템플릿 파라미터에는 자료형 뿐만이 아니라 이렇게 상수를 사용할 수도 있다..

이를 활용하면 함수의 결과값이 컴파일 타임에 결정되기 때문에 일반적인 함수의 파라미터로 숫자를 대입하는 것보다 추가적인 최적화가 있을 수 있다.

 

물론, 이 경우에 _Value가 0보다 크다는 것이 컴파일 타임에 평가할 수 있기 때문에

if 대신에 if constexpr을 사용할 수 있다. (이것 때문에 위의 TMI를 펼쳐보았다.)

 

개인적으로 템플릿을 잘 다루는 능력이 C++ 숙련도의 중요한 척도중 하나라고 생각한다. 템플릿은 편리하고 유용한만큼 문제도 정말 많이 일으키는 놈이기 때문에 템플릿 관련 기능들을 잘 숙지하여 적재적소에 사용해보도록 하자..

+ Recent posts