Examples » Core » Reflection » Mask Trait

Exposing a bit mask type.

In this example, we'll explore how to expose a bit mask along with its bits using cubos::core::reflection::MaskTrait.

#include <cubos/core/reflection/reflect.hpp>

enum class Permissions
{
    None = 0,

    Read = 1,
    Write = 2,
    Execute = 4
};

CUBOS_REFLECT_EXTERNAL_DECL(CUBOS_EMPTY, Permissions);

inline Permissions operator~(Permissions p)
{
    return static_cast<Permissions>(~static_cast<int>(p));
}

inline Permissions operator|(Permissions a, Permissions b)
{
    return static_cast<Permissions>(static_cast<int>(a) | static_cast<int>(b));
}

inline Permissions operator&(Permissions a, Permissions b)
{
    return static_cast<Permissions>(static_cast<int>(a) & static_cast<int>(b));
}
#include <cubos/core/reflection/traits/mask.hpp>
#include <cubos/core/reflection/type.hpp>

using cubos::core::reflection::MaskTrait;
using cubos::core::reflection::Type;

CUBOS_REFLECT_EXTERNAL_IMPL(Permissions)
{
    return Type::create("Permissions")
        .with(MaskTrait{}
                  .withBit<Permissions::Read>("Read")
                  .withBit<Permissions::Write>("Write")
                  .withBit<Permissions::Execute>("Execute"));
}

Notice that we don't include the None type in the trait, as it doesn't correspond to a bit.

int main()
{
    using cubos::core::reflection::reflect;

    const auto& permissionsType = reflect<Permissions>();
    CUBOS_ASSERT(permissionsType.has<MaskTrait>());

    const auto& mask = permissionsType.get<MaskTrait>();
    CUBOS_ASSERT(mask.contains("Read"));
    CUBOS_ASSERT(mask.contains("Write"));
    CUBOS_ASSERT(mask.contains("Execute"));
    CUBOS_ASSERT(!mask.contains("None"));

    auto p = Permissions::Read | Permissions::Write;
    CUBOS_ASSERT(mask.view(&p).test("Read"));
    CUBOS_ASSERT(mask.view(&p).test("Write"));
    CUBOS_ASSERT(!mask.view(&p).test("Execute"));

    for (const auto& b : mask)
    {
        CUBOS_INFO("Type has bit {}", b.name());
    }

    for (const auto& b : mask.view(&p))
    {
        CUBOS_INFO("Value has bit {} set", b.name());
    }

    return 0;
}
// Type has bit "Read"
// Type has bit "Write"
// Type has bit "Execute"
// Value has bit "Read" set
// Value has bit "Write" set