Nullable Trait
Handling null type representation.
The NullableTrait
is a reflection trait designed to provide a mechanism for representing a null state for a specific type. This is particularly useful when working with types that are not literally null but can be conceptually treated as null in certain scenarios.
Consider a scenario where you have a data structure, such as the Entity
struct, which represents an entity with an index
and a generation
. In some cases, you may want to define a special state that indicates the absence of a valid entity instead of checking if both fields are UINT32_MAX
. So, instead of using a separate boolean flag to represent this state, the NullableTrait
allows you to define a custom condition for considering an instance of the type as "null".
So, let's see how we can use this. First, we create a reflectable structure:
#include <cubos/core/reflection/reflect.hpp> struct MyEntity { CUBOS_REFLECT; uint32_t idx; uint32_t generation; };
In the reflection definition, we use the NullableTrait
to define the conditions under which an instance of MyEntity
is considered null, and also another to set it to null.
#include <cubos/core/reflection/traits/nullable.hpp> #include <cubos/core/reflection/type.hpp> // Since we're exposing fields of primitive types (uint32_t), its important to // include the header which defines their reflection. #include <cubos/core/reflection/external/primitives.hpp> using cubos::core::reflection::NullableTrait; using cubos::core::reflection::Type; CUBOS_REFLECT_IMPL(MyEntity) { return Type::create("MyEntity") .with(NullableTrait{[](const void* instance) { const auto* ent = static_cast<const MyEntity*>(instance); return ent->idx == UINT32_MAX && ent->generation == UINT32_MAX; }, [](void* instance) { auto* ent = static_cast<MyEntity*>(instance); ent->idx = UINT32_MAX; ent->generation = UINT32_MAX; }}); }
Now, we can simply use it:
int main() { using cubos::core::reflection::reflect; // Retrieve the reflection information for MyEntity const auto& entityType = reflect<MyEntity>(); // Check if MyEntity has the NullableTrait CUBOS_ASSERT(entityType.has<NullableTrait>()); // Retrieve the NullableTrait for MyEntity const auto& nullableTrait = entityType.get<NullableTrait>(); // Create an instance of MyEntity MyEntity ent{1, 1}; // Check if the instance is not null CUBOS_ASSERT(!nullableTrait.isNull(&ent)); // Set the instance to the null state nullableTrait.setToNull(&ent); // Check if the instance is now null CUBOS_ASSERT(nullableTrait.isNull(&ent)); }