이 글에서는 C++ STL에서 제공하는 std::is_polymorphic 템플릿의 동작 원리, 문법, 그리고 실제 활용 예제를 자세히 살펴보겠습니다.
is_polymorphic은 C++의 <type_traits> 헤더 파일에 포함된 타입 특성(type traits) 템플릿으로, 주어진 클래스가 다형성(polymorphic) 클래스인지 여부를 컴파일 시점에 검사하여 그 결과를 true 또는 false로 반환합니다.
다형성 클래스란?
다형성 클래스란 가상 함수(virtual function)를 직접 선언했거나, 가상 함수가 선언된 클래스(추상 클래스 포함)로부터 상속받은 클래스를 의미합니다. 이러한 클래스는 런타임 다형성을 지원하며, 기반 클래스의 포인터나 참조를 통해 파생 클래스의 가상 함수를 호출할 수 있습니다.
문법
template <class T> is_polymorphic;
매개변수
이 템플릿은 T 타입의 매개변수 하나만 받으며, 해당 타입이 다형성 클래스인지 여부를 검사합니다. 참고로 클래스가 아닌 타입(int, double 등)에 적용하면 항상 false가 반환됩니다.
반환 값
불리언(Boolean) 값을 반환합니다.
- true: 주어진 타입이 다형성 클래스인 경우 (자신 또는 조상 클래스에 가상 함수가 존재)
- false: 주어진 타입이 다형성 클래스가 아닌 경우
예제: 기본 사용법
입력: class B { virtual void fn(){} };
class C : B {};
is_polymorphic<B>::value;
출력: True
입력: class A {};
is_polymorphic<A>::value;
출력: False가상 함수를 가진 클래스 B는 true, 가상 함수가 전혀 없는 클래스 A는 false로 평가됩니다.
예제 1: 가상 함수와 상속 관계 확인
#include <iostream>
#include <type_traits>
using namespace std;
// 가상 함수를 하나 가진 구조체
struct TP {
virtual void display();
};
// TP를 상속받는 구조체
struct TP_2 : TP {
};
// 순수 가상 함수를 가진 추상 클래스
class TP_3 {
virtual void display() = 0;
};
// TP_3를 상속받는 구조체
struct TP_4 : TP_3 {
};
int main() {
cout << boolalpha;
cout << "is_polymorphic 확인 결과:";
cout << "\n 가상 함수를 하나 가진 구조체 TP : " << is_polymorphic<TP>::value;
cout << "\n TP를 상속받은 구조체 TP_2 : " << is_polymorphic<TP_2>::value;
cout << "\n 가상 함수를 하나 가진 클래스 TP_3 : " << is_polymorphic<TP_3>::value;
cout << "\n TP_3를 상속받은 구조체 TP_4 : " << is_polymorphic<TP_4>::value;
return 0;
}실행 결과
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
is_polymorphic 확인 결과: 가상 함수를 하나 가진 구조체 TP : true TP를 상속받은 구조체 TP_2 : true 가상 함수를 하나 가진 클래스 TP_3 : true TP_3를 상속받은 구조체 TP_4 : true
네 경우 모두 true가 출력되었습니다. TP와 TP_3는 가상 함수를 직접 선언했고, TP_2와 TP_4는 비록 스스로 가상 함수를 선언하지 않았지만 가상 함수를 가진 클래스를 상속받았기 때문입니다. 즉, 상속 계층 어딘가에 가상 함수가 존재하기만 하면 다형성 클래스로 판단됩니다.
예제 2: 일반 클래스와의 비교
#include <iostream>
#include <type_traits>
using namespace std;
// 일반 멤버 변수만 가진 구조체
struct TP {
int var;
};
// 가상 함수를 하나 가진 구조체
struct TP_2 {
virtual void display();
};
// TP_2를 상속받는 클래스
class TP_3 : TP_2 {
};
int main() {
cout << boolalpha;
cout << "is_polymorphic 확인 결과:";
cout << "\n 멤버 변수만 가진 구조체 TP : " << is_polymorphic<TP>::value;
cout << "\n 가상 함수를 가진 구조체 TP_2 : " << is_polymorphic<TP_2>::value;
cout << "\n TP_2를 상속받은 클래스 TP_3 : " << is_polymorphic<TP_3>::value;
return 0;
}실행 결과
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
is_polymorphic 확인 결과: 멤버 변수만 가진 구조체 TP : false 가상 함수를 가진 구조체 TP_2 : true TP_2를 상속받은 클래스 TP_3 : true
일반 멤버 변수만 가진 TP는 false로 평가되었고, 가상 함수를 가진 TP_2와 이를 상속받은 TP_3는 true로 평가되었습니다. 이처럼 is_polymorphic은 클래스 설계 시 해당 타입이 vtable(가상 함수 테이블)을 통해 런타임 다형성을 지원하는지 컴파일 시점에 손쉽게 확인할 수 있는 유용한 도구입니다.