#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?