Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ std::is_abstract 템플릿 완벽 정리: 추상 클래스 판별 방법과 예제

이 글에서는 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와 함께 사용하면, 추상 클래스를 잘못 인스턴스화하려는 코드를 컴파일 단계에서 미리 잡아낼 수 있어 더욱 안전한 코드 작성이 가능합니다.