Skip to content

Commit

Permalink
Merge branch 'main' into 362-cuboscoresettings-should-be-moved-to-engine
Browse files Browse the repository at this point in the history
  • Loading branch information
RiscadoA authored Sep 19, 2023
2 parents fb9430e + 456ae3b commit 9a6b87f
Show file tree
Hide file tree
Showing 15 changed files with 567 additions and 12 deletions.
3 changes: 3 additions & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ set(CUBOS_CORE_SOURCE
"src/cubos/core/memory/buffer_stream.cpp"

"src/cubos/core/reflection/type.cpp"
"src/cubos/core/reflection/traits/constructible.cpp"

"src/cubos/core/data/serializer.cpp"
"src/cubos/core/data/deserializer.cpp"
Expand Down Expand Up @@ -88,6 +89,7 @@ set(CUBOS_CORE_INCLUDE
"include/cubos/core/log.hpp"
"include/cubos/core/thread_pool.hpp"

"include/cubos/core/memory/move.hpp"
"include/cubos/core/memory/stream.hpp"
"include/cubos/core/memory/standard_stream.hpp"
"include/cubos/core/memory/buffer_stream.hpp"
Expand All @@ -97,6 +99,7 @@ set(CUBOS_CORE_INCLUDE

"include/cubos/core/reflection/reflect.hpp"
"include/cubos/core/reflection/type.hpp"
"include/cubos/core/reflection/traits/constructible.hpp"

"include/cubos/core/data/serializer.hpp"
"include/cubos/core/data/deserializer.hpp"
Expand Down
44 changes: 44 additions & 0 deletions core/include/cubos/core/memory/move.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/// @file
/// @brief Function @ref cubos::core::memory::move.
/// @ingroup core-memory

#pragma once

namespace cubos::core::memory
{
/// @brief Provides a type which is the same as the given type, but without any references.
/// @note This is a replacement for `std::remove_reference`, which allows us to avoid including
/// the entire `<type_traits>` header.
/// @tparam T
template <typename T>
struct RemoveReference
{
/// @brief Type without references.
using Type = T;
};

template <typename T>
struct RemoveReference<T&>
{
using Type = T;
};

template <typename T>
struct RemoveReference<T&&>
{
using Type = T;
};

/// @brief Returns an R-value reference to the given value
/// @note This is a replacement for `std::move`, which allows us to avoid including the entire
/// `<utility>` header.
/// @tparam T Value type.
/// @param value Value to move.
/// @return Moved value.
/// @ingroup core-memory
template <typename T>
typename RemoveReference<T>::Type&& move(T&& value)
{
return static_cast<typename RemoveReference<T>::Type&&>(value);
}
} // namespace cubos::core::memory
7 changes: 7 additions & 0 deletions core/include/cubos/core/reflection/module.dox
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,11 @@ namespace cubos::core::reflection
/// @defgroup core-reflection Reflection
/// @ingroup core
/// @brief Provides utilities useful for handling type-erased data.
/// @see Take a look at the @ref examples-core-reflection examples for demonstrations of this
/// module.
///
/// @note By type-erased data, we mean that data is stored in a generic container, for example,
/// through a void pointer, such that its type is not known at compile-time. This could be
/// useful, for example, to integrate scripts into the engine, since types defined there are
/// only know when the application is running.
} // namespace cubos::core::reflection
168 changes: 168 additions & 0 deletions core/include/cubos/core/reflection/traits/constructible.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/// @file
/// @brief Class @ref cubos::core::reflection::ConstructibleTrait.
/// @ingroup core-reflection

#pragma once

#include <cstddef>

#include <cubos/core/memory/move.hpp>

namespace cubos::core::reflection
{
/// @brief Describes how a reflected type may be constructed and destructed.
/// @see See @ref examples-core-reflection-traits-constructible for an example of using this
/// trait.
/// @ingroup core-reflection
class ConstructibleTrait
{
public:
/// @brief Function pointer to the destructor of a type.
/// @param instance Pointer to the instance to destruct.
using Destructor = void (*)(void* instance);

/// @brief Function pointer to the default constructor of a type.
/// @param instance Pointer to the location to construct the instance at.
using DefaultConstructor = void (*)(void* instance);

/// @brief Function pointer to the copy constructor of a type.
/// @param instance Pointer to the location to construct the instance at.
/// @param other Pointer to the instance to copy construct from.
using CopyConstructor = void (*)(void* instance, const void* other);

/// @brief Function pointer to the move constructor of a type.
/// @param instance Pointer to the location to construct the instance at.
/// @param other Pointer to the instance to move construct from.
using MoveConstructor = void (*)(void* instance, void* other);

/// @brief Builder for @ref ConstructibleTrait.
template <typename T>
class Builder;

/// @brief Constructs.
/// @param size Size of the type in bytes.
/// @param alignment Alignment of the type in bytes (must be a power of two).
/// @param destructor Function pointer to the destructor of the type.
ConstructibleTrait(std::size_t size, std::size_t alignment, void (*destructor)(void*));

/// @brief Returns a trait builder for the given type.
/// @tparam T Type to build a trait for.
/// @return Trait builder.
template <typename T>
static Builder<T> typed();

/// @brief Sets the default constructor of the type.
///
/// Aborts if the default constructor has already been set.
///
/// @param defaultConstructor Function pointer to the default constructor of the type.
/// @return Trait.
ConstructibleTrait&& withDefaultConstructor(DefaultConstructor defaultConstructor) &&;

/// @brief Sets the copy constructor of the type.
///
/// Aborts if the copy constructor has already been set.
///
/// @param copyConstructor Function pointer to the copy constructor of the type.
/// @return Trait.
ConstructibleTrait&& withCopyConstructor(CopyConstructor copyConstructor) &&;

/// @brief Sets the move constructor of the type.
///
/// Aborts if the copy constructor has already been set.
///
/// @param moveConstructor Function pointer to the move constructor of the type.
/// @return Trait.
ConstructibleTrait&& withMoveConstructor(MoveConstructor moveConstructor) &&;

/// @brief Returns the size of the type in bytes.
/// @return Size of the type in bytes.
std::size_t size() const;

/// @brief Returns the alignment of the type in bytes.
/// @return Alignment of the type in bytes.
std::size_t alignment() const;

/// @brief Destructs an instance of the type.
/// @param instance Pointer to the instance to destruct.
void destruct(void* instance) const;

/// @brief Default constructs an instance of the type.
/// @param instance Pointer to the location to construct the instance at.
/// @return Whether default construction is supported.
bool defaultConstruct(void* instance) const;

/// @brief Copy constructs an instance of the type.
/// @param instance Pointer to the location to construct the instance at.
/// @param other Pointer to the instance to copy construct from.
/// @return Whether copy construction is supported.
bool copyConstruct(void* instance, const void* other) const;

/// @brief Move constructs an instance of the type.
/// @param instance Pointer to the location to construct the instance at.
/// @param other Pointer to the instance to move construct from.
/// @return Whether move construction is supported.
bool moveConstruct(void* instance, void* other) const;

private:
std::size_t mSize;
std::size_t mAlignment;
Destructor mDestructor;
DefaultConstructor mDefaultConstructor;
CopyConstructor mCopyConstructor;
MoveConstructor mMoveConstructor;
};

template <typename T>
class ConstructibleTrait::Builder
{
public:
/// @brief Constructs.
Builder()
: mTrait(sizeof(T), alignof(T), [](void* instance) { static_cast<T*>(instance)->~T(); })
{
}

/// @brief Returns the constructed trait.
/// @return Constructed trait.
ConstructibleTrait build() &&
{
return mTrait;
}

/// @brief Sets the copy constructor of the type.
/// @return Builder.
Builder&& withDefaultConstructor() &&
{
mTrait = memory::move(mTrait).withDefaultConstructor([](void* instance) { new (instance) T(); });
return memory::move(*this);
}

/// @brief Sets the copy constructor of the type.
/// @return Builder.
Builder&& withCopyConstructor() &&
{
mTrait = memory::move(mTrait).withCopyConstructor(
[](void* instance, const void* other) { new (instance) T(*static_cast<const T*>(other)); });
return memory::move(*this);
}

/// @brief Sets the move constructor of the type.
/// @return Builder.
Builder&& withMoveConstructor() &&
{
mTrait = memory::move(mTrait).withMoveConstructor(
[](void* instance, void* other) { new (instance) T(memory::move(*static_cast<T*>(other))); });
return memory::move(*this);
}

private:
ConstructibleTrait mTrait;
};

template <typename T>
ConstructibleTrait::Builder<T> ConstructibleTrait::typed()
{
return Builder<T>();
}
} // namespace cubos::core::reflection
42 changes: 42 additions & 0 deletions core/include/cubos/core/reflection/traits/constructible_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/// @file
/// @brief Utilities for @ref cubos::core::reflection::ConstructibleTrait.
/// @note Avoid using this header as it includes `<type_traits>`.
/// @ingroup core-reflection

#pragma once

#include <type_traits>

#include <cubos/core/reflection/traits/constructible.hpp>

namespace cubos::core::reflection
{
/// @brief Returns a ConstructibleTrait with the default, copy and move constructors, set only
/// if the type has them.
/// @warning Avoid using this function as its header includes `<type_traits>`.
/// @tparam T Type.
/// @return ConstructibleTrait.
/// @ingroup core-reflection
template <typename T>
ConstructibleTrait autoConstructibleTrait()
{
auto builder = ConstructibleTrait::typed<T>();

if constexpr (std::is_default_constructible<T>::value)
{
builder = memory::move(builder).withDefaultConstructor();
}

if constexpr (std::is_copy_constructible<T>::value)
{
builder = memory::move(builder).withCopyConstructor();
}

if constexpr (std::is_move_constructible<T>::value)
{
builder = memory::move(builder).withMoveConstructor();
}

return memory::move(builder).build();
}
} // namespace cubos::core::reflection
2 changes: 2 additions & 0 deletions core/include/cubos/core/reflection/traits/module.dox
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// @dir
/// @brief @ref core-reflection module built-in traits.
1 change: 1 addition & 0 deletions core/samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ endmacro()

make_sample(DIR "logging")
make_sample(DIR "reflection/basic")
make_sample(DIR "reflection/traits/constructible")
make_sample(DIR "data/fs/embedded_archive" SOURCES "embed.cpp")
make_sample(DIR "data/fs/standard_archive")
make_sample(DIR "data/serialization")
Expand Down
4 changes: 2 additions & 2 deletions core/samples/reflection/basic/page.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Reflection {#examples-core-reflection-basic}
# Basic Usage {#examples-core-reflection-basic}

@brief Using the reflection system.
@brief Defining and using reflectable types.

Lets say you have a type `Person`, which you want to be able to reflect. You
can declare it as reflectable using the macro @ref CUBOS_REFLECT, for example,
Expand Down
6 changes: 6 additions & 0 deletions core/samples/reflection/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Reflection {#examples-core-reflection}

@brief Using the @ref core-reflection module.

- @subpage examples-core-reflection-basic - @copybrief examples-core-reflection-basic
- @subpage examples-core-reflection-traits-constructible - @copybrief examples-core-reflection-traits-constructible
48 changes: 48 additions & 0 deletions core/samples/reflection/traits/constructible/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <cubos/core/log.hpp>

/// [Scale declaration]
#include <cubos/core/reflection/reflect.hpp>

struct Scale
{
CUBOS_REFLECT;
float value = 1.0F;
};
/// [Scale declaration]

/// [Scale definition]
#include <cubos/core/reflection/traits/constructible.hpp>
#include <cubos/core/reflection/type.hpp>

using cubos::core::reflection::ConstructibleTrait;
using cubos::core::reflection::Type;

CUBOS_REFLECT_IMPL(Scale)
{
return Type::create("Scale").with(ConstructibleTrait::typed<Scale>().withDefaultConstructor().build());
}
/// [Scale definition]

/// [Accessing the trait]
int main()
{
using cubos::core::reflection::reflect;

const auto& scaleType = reflect<Scale>();
CUBOS_ASSERT(scaleType.has<ConstructibleTrait>());
const auto& constructible = scaleType.get<ConstructibleTrait>();
/// [Accessing the trait]

/// [Creating a default instance]
// Allocate memory for the instance and default-construct it.
void* instance = operator new(constructible.size());
CUBOS_ASSERT(constructible.defaultConstruct(instance));
CUBOS_ASSERT(static_cast<Scale*>(instance)->value == 1.0F);
/// [Creating a default instance]

/// [Destroying the instance]
// Destroy the instance and deallocate its memory.
constructible.destruct(instance);
operator delete(instance);
}
/// [Destroying the instance]
Loading

0 comments on commit 9a6b87f

Please sign in to comment.