Сериализация перечислителя vulkan.hpp с хлопьями, как мне это сделать?

#c #serialization #vulkan #cereal

Вопрос:

Перечисления vulan в классе hpp используют оболочку шаблона для определения побитовых операций для обеспечения безопасности.

Это выглядит примерно так:

 
template<typename BitType> class Flags
{
  public:
    using MaskType = typename std::underlying_type<BitType>::type;

    // constructors
    constexpr Flags()
        : m_mask(0)
    {
    }

    constexpr Flags(BitType bit)
        : m_mask(static_cast<MaskType>(bit))
    {
    }

    constexpr Flags(Flags<BitType> constamp; rhs)
        : m_mask(rhs.m_mask)
    {
    }

    constexpr Flags(MaskType flags)
        : m_mask(flags)
    {
    }

    auto operator<=>(Flags<BitType> constamp;) const = defau<

    // logical operator
    constexpr bool operator!() const { return !m_mask; }

    // bitwise operators
    constexpr Flags<BitType> operatoramp;(Flags<BitType> constamp; rhs) const
    {
        return Flags<BitType>(m_mask amp; rhs.m_mask);
    }

    constexpr Flags<BitType> operator|(Flags<BitType> constamp; rhs) const
    {
        return Flags<BitType>(m_mask | rhs.m_mask);
    }

    constexpr Flags<BitType> operator^(Flags<BitType> constamp; rhs) const
    {
        return Flags<BitType>(m_mask ^ rhs.m_mask);
    }

    // assignment operators
    constexpr Flags<BitType>amp; operator=(Flags<BitType> constamp; rhs)
    {
        m_mask = rhs.m_mask;
        return *this;
    }

    constexpr Flags<BitType>amp; operator|=(Flags<BitType> constamp; rhs)
    {
        m_mask |= rhs.m_mask;
        return *this;
    }

    constexpr Flags<BitType>amp; operatoramp;=(Flags<BitType> constamp; rhs)
    {
        m_mask amp;= rhs.m_mask;
        return *this;
    }

    constexpr Flags<BitType>amp; operator^=(Flags<BitType> constamp; rhs)
    {
        m_mask ^= rhs.m_mask;
        return *this;
    }

    // Arithmetic operators
    constexpr Flags<BitType>amp; operator*=(Flags<BitType> constamp; rhs)
    {
        m_mask *= rhs.m_mask;
        return *this;
    }

    constexpr Flags<BitType>amp; operator =(Flags<BitType> constamp; rhs)
    {
        m_mask  = rhs.m_mask;
        return *this;
    }

    constexpr Flags<BitType>amp; operator*(Flags<BitType> constamp; rhs)
    {
        return {m_mask * rhs.m_mask};
    }

    constexpr Flags<BitType>amp; operator (Flags<BitType> constamp; rhs)
    {
        return {m_mask   rhs.m_mask};
    }

    // cast operators
    explicit constexpr operator bool() const { return !!m_mask; }

    explicit constexpr operator MaskType() const { return m_mask; }

  private:
    MaskType m_mask;
};
 

Проблема в том, что если вы определяете функцию хлопьев напрямую, это, по-видимому, приводит к тому, что хлопья превращаются в ад, который через несколько минут заканчивается в segfault.

т. е. это плохо:

 // cereal function for serialization.
template <class Archive, typename BitType>
void serialize( Archiveamp; archive, Flags<BitType>amp; tag )
{
    archive(
        tag
    );
}
 

Один из способов обойти это определить тип маски как общедоступный, тогда вы можете сделать:

 // cereal function for serialization.
template <class Archive, typename BitType>
void serialize( Archiveamp; archive, Flags<BitType>amp; tag )
{
    archive(
        tag.m_mask
    );
}
 

Это работает нормально, но означает, что вам придется изменить заголовок vulkan.hpp, что является ужасной идеей.

В качестве альтернативы вы можете попробовать сделать это:

 // cereal function for serialization.
template <class Archive, typename BitType>
void serialize( Archiveamp; archive, Flags<BitType>amp; tag )
{
    archive(
        (BitType)tag
    );
}
 

That doesn’t end in a segfault but cereal does not load the correct values when I do this, in fact the serialized data is correct but when it gets loaded all teh vulkan enum fields are set to 0 instead of the stored value.

I am out fo ideas, how can get cereal to properly load this data?