이 글에서는 C++ STL에서 제공하는 std::is_abstract 템플릿의 동작 원리, 문법, 그리고 실제 사용 예제를 자세히 살펴보겠습니다.
is_abstract 템플릿은 특정 클래스가 추상 클래스(abstract class)인지 아닌지를 컴파일 타임에 확인할 수 있도록 도와주는 타입 특성(type trait)입니다.
추상 클래스란 무엇인가?
추상 클래스는 최소한 하나 이상의 순수 가상 함수(pure virtual function)를 포함하고 있는 클래스를 의미합니다.
그렇다면 왜 추상 클래스를 사용할까요? 함수를 선언할 때 그 구현 내용을 알 수 없는 경우가 있습니다. 즉, 해당 함수가 시스템에 반드시 존재해야 한다는 것은 확실하지만, 구체적으로 어떤 동작을 해야 하는지는 나중에 결정해야 하는 상황이 발생합니다. 이럴 때 구현부 없이 선언만 존재하는 순수 가상 함수를 선언하면 매우 유용합니다.
따라서 클래스의 인스턴스를 통해 해당 클래스가 추상 클래스인지 확인하고 싶을 때 is_abstract()를 사용합니다.
is_abstract()는 integral_constant로부터 상속되며, 클래스 T의 인스턴스가 다형적(polymorphic) 클래스 타입인지 여부에 따라 true_type 또는 false_type을 반환합니다.
문법(Syntax)
template <class T> struct is_abstract;
매개변수(Parameters)
이 템플릿은 단 하나의 매개변수 T만 가질 수 있으며, T는 추상 클래스인지 검사할 대상이 되는 클래스 타입입니다.
반환 값(Return Value)
이 함수는 bool 타입의 값, 즉 true 또는 false를 반환합니다.
- true: T가 추상 클래스인 경우
- false: T가 추상 클래스가 아닌 경우
예제 1
#include <iostream>
#include <type_traits>
using namespace std;
struct TP_1 {
int var;
};
struct TP_2 {
virtual void dummy() = 0;
};
class TP_3 : TP_2 {
};
int main() {
cout << boolalpha;
cout << "checking for is_abstract: ";
cout << "\nstructure TP_1 with one variable :"<< is_abstract<TP_1>::value;
cout << "\nstructure TP_2 with one virtual variable : "<< is_abstract<TP_2>::value;
cout << "\nclass TP_3 which is derived from TP_2 structure : "<< is_abstract<TP_3>::value;
return 0;
}실행 결과
위 코드를 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.
checking for is_abstract: structure TP_1 with one variable : false structure TP_2 with one virtual variable : true class TP_3 which is derived from TP_2 structure : true
결과 분석
- TP_1: 일반 멤버 변수만 가지고 있고 순수 가상 함수가 없으므로 false가 반환됩니다.
- TP_2: 순수 가상 함수(
virtual void dummy() = 0;)를 포함하고 있으므로 true가 반환됩니다. - TP_3: 추상 클래스인 TP_2를 상속받았지만 순수 가상 함수를 오버라이드하지 않았기 때문에 역시 추상 클래스로 판단되어 true가 반환됩니다.
예제 2
#include <iostream>
#include <type_traits>
using namespace std;
struct TP_1 {
virtual void dummy() = 0;
};
class TP_2 {
virtual void dummy() = 0;
};
struct TP_3 : TP_2 {
};
int main() {
cout << boolalpha;
cout << "checking for is_abstract: ";
cout << "\nstructure TP_1 with one virtual function :"<< is_abstract<TP_1>::value;
cout << "\nclass TP_2 with one virtual function : "<< is_abstract<TP_2>::value;
cout << "\nstructure TP_3 which is derived from TP_2 class : "<< is_abstract<TP_3>::value;
return 0;
}실행 결과
위 코드를 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.
checking for is_abstract: structure TP_1 with one virtual function : true class TP_2 with one virtual function : true structure TP_3 which is derived from TP_2 class : true
결과 분석
- TP_1(struct): 순수 가상 함수를 포함하고 있으므로 true가 반환됩니다. struct와 class 모두 추상 클래스가 될 수 있습니다.
- TP_2(class): 마찬가지로 순수 가상 함수를 포함하고 있어 true가 반환됩니다.
- TP_3: 추상 클래스 TP_2를 상속받으면서 순수 가상 함수를 구현하지 않았으므로 true가 반환됩니다.
마무리
std::is_abstract는 템플릿 메타프로그래밍에서 타입의 성질을 컴파일 타임에 검사할 때 활용되는 유용한 도구입니다. 특히 SFINAE나 static_assert와 함께 사용하면, 추상 클래스를 잘못 인스턴스화하려는 코드를 컴파일 단계에서 미리 잡아낼 수 있어 더욱 안전한 코드 작성이 가능합니다.