18. 템플릿 특수화, constexpr

  1. 템플릿 특수화 (Template Specialization)
  2. constexpr
  3. 활용



1. 템플릿 특수화 (Template Specialization)

템플릿 특수화는 C++의 템플릿 기능 중 하나로, 특정 타입에 대해 템플릿의 동작을 다르게 정의하는 방법이다. 이를 통해 일반적인 템플릿을 사용하면서도 특정 타입에 대한 맞춤형 구현을 제공할 수 있다.

템플릿 특수화는 특정 타입에 대해 별도의 동작을 구현하려 할 때 사용된다.


일반 템플릿

template <typename T>
class MyClass {
public:
    void Show() {
        cout << "일반 템플릿" << endl;
    }
};


명시적 특수화

특정 타입에 대해 별도의 동작을 구현한다.


template <>
class MyClass<int> {
public:
    void Show() {
        cout << "int 타입 특수화" << endl;
    }
};


부분 특수화

여러 템플릿 인자 중 일부만 특정 타입으로 구현할 때 사용된다.


template <typename T1, typename T2>
class MyClass {
public:
    void Show() {
        cout << "일반 템플릿" << endl;
    }
};

// 두 번째 타입이 int인 경우 특수화
template <typename T1>
class MyClass<T1, int> {
public:
    void Show() {
        cout << "두 번째 타입이 int일 때 특수화" << endl;
    }
};


멤버 함수 특수화

특정 멤버 함수만 특수화할 수도 있다.


template <typename T>
class MyClass {
public:
    void Show() {
        cout << "일반 템플릿" << endl;
    }
};

// int 타입에 대해서만 Show 함수 특수화
template <>
void MyClass<int>::Show() {
    cout << "int 타입 특수화" << endl;
}


함수 템플릿 특수화

클래스 뿐만 아니라 함수도 템플릿 특수화가 가능하다.


template <typename T>
void Print(T value) {
    cout << "일반 템플릿: " << value << endl;
}

// int 타입에 대한 특수화
template <>
void Print<int>(int value) {
    cout << "int 특수화: " << value << endl;
}




2. constexpr

constexpr은 컴파일 타임에 값을 결정할 수 있는 상수 표현을 만들기 위해 사용된다.

일반적인 const 타입은 해당 라인이 실행될 때 상수화가 된다면, constexpr 의 경우 컴파일 타임에 상수화가 되어 값이 결정된다.


constexpr 변수

constexpr 변수는 반드시 컴파일 타임에 값이 결정되어야 한다. 따라서 반드시 constexpr 또는 리터럴 값으로 초기화해야 한다.


constexpr int x = 10;  // 컴파일 타임 상수
constexpr double y = 3.14;  // 가능

int main() {
    constexpr int z = x + 5;  // 컴파일 타임 연산 가능

    int a = 10;
    constexpr int b = a + 5;  // a는 런타임 변수라서 constexpr로 선언 불가, 컴파일 에러
    return 0;
}


constexpr 함수

C++11부터 함수도 컴파일 타임에 실행될 수 있도록 constexpr 함수가 추가되었다.

이후, C++11에서는 constexpr 함수가 반드시 컴파일 타임에 실행되어야 했지만, C++14부터는 런타임에서도 사용 가능하도록 변경되었다.


constexpr int Square(int x) {
    return x * x;
}

int main() {
    constexpr int result = Square(5);  // 컴파일 타임 연산
    int num = 10;
    int runtime_result = Square(num);  // 런타임 연산 (C++14부터 가능)
    return 0;
}


if constexpr 조건문

C++17부터는 컴파일 타임 조건문인 if constexpr이 추가되어 조건에 따라 코드를 제거할 수 있다.

(예시 코드는 아래 활용 참고)




3. 활용

템플릿 특수화와 constexpr을 활용하여 타입 비교를 구현할 수 있다.



template <class, class>
constexpr bool is_same_v = false; // 기본 템플릿은 무조건 false를 반환한다.
template <class _Ty>
constexpr bool is_same_v<_Ty, _Ty> = true;  // 템플릿 특수화로 같은 타입 두개가 입력되었을 때 true를 반환하도록 한다.

// 타입을 비교하여 결과를 반환해 주는 함수.
template<typename T>
ASSET_TYPE GetAssetType()
{
	if constexpr (is_same_v<CMesh, T>)
		return MESH;
	else if constexpr (is_same_v<CTexture, T>)
		return TEXTURE;
	else if constexpr (is_same_v<CMaterial, T>)
		return MATERIAL;
	else if constexpr (is_same_v<CGraphicShader, T>)
		return GRAPHIC_SHADER;
	else if constexpr (is_same_v<CComputeShader, T>)
		return COMPUTE_SHADER;
	else if constexpr (is_same_v<CSprite, T>)
		return SPRITE;
	else if constexpr (is_same_v<CFlipbook, T>)
		return FLIPBOOK;
}