std::is_empty - empty class (C++11~)

2024. 8. 4. 22:42프로그래밍 언어/C++

출처: https://en.cppreference.com/w/cpp/types/is_empty

 

std::is_empty - cppreference.com

template< class T > struct is_empty; (since C++11) std::is_empty is a UnaryTypeTrait. If T is an empty type (that is, a non-union class type with no non-static data members other than bit-fields of size 0, no virtual functions, no virtual base classes, and

en.cppreference.com

예제: ChatGPT 생성.

 

* 사용법

 - 헤더: <type_traits>

 - C++11: std::is_empty<Type>::value

 - C++17: std::is_empty_v<Type>

 

* 용도 (다른 글에서 연관된 내용이 나오는 경우 참조할 수 있도록 추가 예정)

 - 상속을 위한 기본 클래스로 사용.

 - 템플릿 인자 (타입)으로 활용: 특정 타입에 대한 정보를 전달 또는 타입에 따라 다른 동작을 수행하도록 할 수 있다.

 - RTTI (런타임 타임 정보)로 활용: 타입 정보를 통한 활용.

 - 태그 또는 플래그 용도: 특정 상태나 속성을 나타내는 태그 또는 플래그 역할, 존재 여부나 상속 관계를 통해 특정 의미를 부여할 수 있다.

 

* 특징

 - empty class의 객체는 크기가 0이 아닌 1바이트를 차지한다. 객체가 고유한 주소를 가져야 하기 때문에 C++표준에서 정함.

 

* 설명

 - 특정 클래스가 비어 있는지 여부를 컴파일 타임에 확인할 수 있는 Type Traits 기술.

 - 빈 클래스의 조건

  1. union이 아니어야 한다. (class 또는 struct 이어야 함)

  2. 크기가 0인 비트 필드를 제외한 비정적(non-static) 데이터 멤버가 없어야 한다.

  3. 클래스에 가상 함수가 없어야 한다.

  4. 클래스가 가상 상속(virtual inheritance)을 사용하여 기본 클래스를 상속받지 않아야 한다.

  5. 클래스가 상속받는 기본 클래스도 빈 클래스여야 한다.

 

#include <iostream>
#include <type_traits> // std::is_empty를 사용하기 위해 필요한 헤더 파일

// 1. union이 아니어야 한다. (class 또는 struct 이어야 함)
class NonUnionClass {}; // 비공용 클래스
union UnionType {}; // 공용체

// 2. 크기가 0인 비트 필드를 제외한 비정적(non-static) 데이터 멤버가 없어야 한다.
class EmptyClass1 {}; // 비정적 데이터 멤버가 없음

class NonEmptyClass {
    int data; // 비정적 데이터 멤버가 있음
};

class EmptyClass2 {
    int : 0; // 크기가 0인 비트 필드 (비정적 데이터 멤버로 간주되지 않음)
};

// 3. 클래스에 가상 함수가 없어야 한다.
class EmptyClass3 {
    void func() {} // 비가상 함수
};

class NonEmptyClassWithVirtual {
    virtual void func() {} // 가상 함수가 있음
};

// 4. 클래스가 가상 상속(virtual inheritance)을 사용하여 기본 클래스를 상속받지 않아야 한다.
class Base {};

class EmptyClass4 : public Base {}; // 가상 상속이 아님

class NonEmptyClassWithVirtualBase : virtual public Base {}; // 가상 상속

// 5. 클래스가 상속받는 기본 클래스도 빈 클래스여야 한다.
class EmptyBase {};

class EmptyClass5 : public EmptyBase {}; // 빈 기본 클래스를 상속

class NonEmptyBase {
    int data; // 비정적 데이터 멤버가 있는 기본 클래스
};

class NonEmptyClassWithNonEmptyBase : public NonEmptyBase {}; // 비빈 기본 클래스를 상속

// 모든 조건을 만족하는 빈 클래스 예제
class EmptyClass {
public:
    void doSomething() {} // 비정적 멤버 함수
};

class AnotherEmptyClass : public EmptyClass {}; // 빈 기본 클래스를 상속

int main() {
    std::cout << std::boolalpha; // bool 값을 true/false로 출력하기 위해 설정

    std::cout << "NonUnionClass is empty: " << std::is_empty<NonUnionClass>::value << std::endl; // true
    std::cout << "UnionType is empty: " << std::is_empty<UnionType>::value << std::endl; // false

    std::cout << "EmptyClass1 is empty: " << std::is_empty<EmptyClass1>::value << std::endl; // true
    std::cout << "NonEmptyClass is empty: " << std::is_empty<NonEmptyClass>::value << std::endl; // false
    std::cout << "EmptyClass2 is empty: " << std::is_empty<EmptyClass2>::value << std::endl; // true

    std::cout << "EmptyClass3 is empty: " << std::is_empty<EmptyClass3>::value << std::endl; // true
    std::cout << "NonEmptyClassWithVirtual is empty: " << std::is_empty<NonEmptyClassWithVirtual>::value << std::endl; // false

    std::cout << "EmptyClass4 is empty: " << std::is_empty<EmptyClass4>::value << std::endl; // true
    std::cout << "NonEmptyClassWithVirtualBase is empty: " << std::is_empty<NonEmptyClassWithVirtualBase>::value << std::endl; // false

    std::cout << "EmptyClass5 is empty: " << std::is_empty<EmptyClass5>::value << std::endl; // true
    std::cout << "NonEmptyClassWithNonEmptyBase is empty: " << std::is_empty<NonEmptyClassWithNonEmptyBase>::value << std::endl; // false

    std::cout << "EmptyClass is empty: " << std::is_empty<EmptyClass>::value << std::endl; // true
    std::cout << "AnotherEmptyClass is empty: " << std::is_empty<AnotherEmptyClass>::value << std::endl; // true

    return 0;
}

 

NonUnionClass is empty: true
UnionType is empty: false
EmptyClass1 is empty: true
NonEmptyClass is empty: false
EmptyClass2 is empty: true
EmptyClass3 is empty: true
NonEmptyClassWithVirtual is empty: false
EmptyClass4 is empty: true
NonEmptyClassWithVirtualBase is empty: false
EmptyClass5 is empty: true
NonEmptyClassWithNonEmptyBase is empty: false
EmptyClass is empty: true
AnotherEmptyClass is empty: true