개발하는 리프터 꽃게맨입니다.

C++ RTTI 오버헤드 없는 Type Info 본문

카테고리 없음

C++ RTTI 오버헤드 없는 Type Info

파워꽃게맨 2024. 9. 26. 14:48
#include <iostream>
#include <typeinfo>
#include <unordered_set>
#include <unordered_map>

struct TypeID
{
    bool operator==(const TypeID& other) const
    {
        return ID == other.ID;
    }

    size_t ID = {};
};

namespace std
{
    template <>
    struct hash<TypeID>
    {
        size_t operator()(const TypeID& typeID) const
        {
            return std::hash<size_t>{}(typeID.ID);
        }
    };
}

class TypeInfoBase
{
protected:
    static TypeID InstTypeID()
    {
        TypeID result = {  };
        result.ID = m_currentTypeID;
        m_currentTypeID += ID_COUNT_STEP;

        return result;
    }

private:
    enum {ID_COUNT_STEP = 256};
    inline static size_t m_currentTypeID = 0;
};

template <typename Type>
class TypeInfo : TypeInfoBase
{
public:
    static TypeID GetID()
    {
        static TypeID id = InstTypeID();
        return id;
    }

    static const char* GetName()
    {
        static const char* typeName = typeid(Type).name();
        return typeName;
    }
};

std::unordered_map<TypeID, std::string> um;

void Insert(TypeID key, std::string str)
{
    um[key] = str;
}

int main()
{
    Insert(TypeInfo<int>::GetID(), "Hello");
    Insert(TypeInfo<float>::GetID(), "My");
    Insert(TypeInfo<char>::GetID(), "Name");
    Insert(TypeInfo<std::string>::GetID(), "Is");
    Insert(TypeInfo<short>::GetID(), "CM");

    return 0;
}

 

typeid는 다형성을 가진 클래스 안에서만 RTTI로 돕니다.

그래서 현재 위 코드는 RTTI를 비활성화 한 상태에서도 잘 돌아갑니다.

 

typeid로 해쉬테이블을 사용하면 좋을 것 같아서 만들어봤습니다.

typeid.hash 를 사용하면 되지 않느냐.. 라고 의문을 가질 수 있으나

hash를 호출할 때마다 중복된 해쉬 계산을 하니 그게 좀 마음에 걸렸습니다.

이렇게 하면 ID를 한 번만 계산하고 재호출시에는 캐싱된 ID를 가져와서 사용합니다.

 

InitTypeID 내부 구현을 고치면 ID를 만들어내는 매커니즘을 바꿀 수 있습니다.

해쉬 함수를 사용하는게 일반적이겠죠.