Skip to content

Commit

Permalink
refactor(reflection): Constructible has*
Browse files Browse the repository at this point in the history
  • Loading branch information
RiscadoA committed Oct 6, 2023
1 parent 5d133d8 commit 1b6d0db
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 47 deletions.
24 changes: 18 additions & 6 deletions core/include/cubos/core/reflection/traits/constructible.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,26 +83,38 @@ namespace cubos::core::reflection
/// @return Alignment of the type in bytes.
std::size_t alignment() const;

/// @brief Checks if default construction is supported.
/// @return Whether the operation is supported.
bool hasDefaultConstruct() const;

/// @brief Checks if copy construction is supported.
/// @return Whether the operation is supported.
bool hasCopyConstruct() const;

/// @brief Checks if move construction is supported.
/// @return Whether the operation is supported.
bool hasMoveConstruct() 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.
/// @note Aborts if @ref hasDefaultConstruct() returns false.
/// @param instance Pointer to the location to construct the instance at.
/// @return Whether default construction is supported.
bool defaultConstruct(void* instance) const;
void defaultConstruct(void* instance) const;

/// @brief Copy constructs an instance of the type.
/// @note Aborts if @ref hasCopyConstruct() returns false.
/// @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;
void copyConstruct(void* instance, const void* other) const;

/// @brief Move constructs an instance of the type.
/// @note Aborts if @ref hasMoveConstruct() returns false.
/// @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;
void moveConstruct(void* instance, void* other) const;

private:
std::size_t mSize;
Expand Down
2 changes: 1 addition & 1 deletion core/samples/reflection/traits/constructible/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ int main()
/// [Creating a default instance]
// Allocate memory for the instance and default-construct it.
void* instance = operator new(constructible.size());
CUBOS_ASSERT(constructible.defaultConstruct(instance));
constructible.defaultConstruct(instance);
CUBOS_ASSERT(static_cast<Scale*>(instance)->value == 1.0F);
/// [Creating a default instance]

Expand Down
8 changes: 0 additions & 8 deletions core/samples/reflection/traits/constructible/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,6 @@ constructor stored in the trait:

@snippet reflection/traits/constructible/main.cpp Creating a default instance

The @ref cubos::core::reflection::ConstructibleTrait::defaultConstruct
"defaultConstruct" method returns a boolean which indicates if the type has a
default constructor or not. In this case, since we added the default
constructor to the trait, it will return `true`.

This could be useful, for example, to fallback from using `moveConstruct` to
`copyConstruct`, if the first isn't available.

Don't forget to destroy the instance manually when you're done with it:

@snippet reflection/traits/constructible/main.cpp Destroying the instance
Expand Down
46 changes: 23 additions & 23 deletions core/src/cubos/core/reflection/traits/constructible.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,40 +45,40 @@ std::size_t ConstructibleTrait::alignment() const
return mAlignment;
}

void ConstructibleTrait::destruct(void* instance) const
bool ConstructibleTrait::hasDefaultConstruct() const
{
mDestructor(instance);
return mDefaultConstructor != nullptr;
}

bool ConstructibleTrait::defaultConstruct(void* instance) const
bool ConstructibleTrait::hasCopyConstruct() const
{
if (mDefaultConstructor != nullptr)
{
mDefaultConstructor(instance);
return true;
}
return mCopyConstructor != nullptr;
}

return false;
bool ConstructibleTrait::hasMoveConstruct() const
{
return mMoveConstructor != nullptr;
}

bool ConstructibleTrait::copyConstruct(void* instance, const void* other) const
void ConstructibleTrait::destruct(void* instance) const
{
if (mCopyConstructor != nullptr)
{
mCopyConstructor(instance, other);
return true;
}
mDestructor(instance);
}

return false;
void ConstructibleTrait::defaultConstruct(void* instance) const
{
CUBOS_ASSERT(this->hasDefaultConstruct());
mDefaultConstructor(instance);
}

bool ConstructibleTrait::moveConstruct(void* instance, void* other) const
void ConstructibleTrait::copyConstruct(void* instance, const void* other) const
{
if (mMoveConstructor != nullptr)
{
mMoveConstructor(instance, other);
return true;
}
CUBOS_ASSERT(this->hasCopyConstruct());
mCopyConstructor(instance, other);
}

return false;
void ConstructibleTrait::moveConstruct(void* instance, void* other) const
{
CUBOS_ASSERT(this->hasMoveConstruct());
mMoveConstructor(instance, other);
}
15 changes: 9 additions & 6 deletions core/tests/reflection/traits/constructible.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ TEST_CASE("reflection::ConstructibleTrait")
auto trait = ConstructibleTrait::typed<DetectDestructor>().build();
DetectDestructor detector{};

CHECK_FALSE(trait.defaultConstruct(ptr));
CHECK_FALSE(trait.copyConstruct(ptr, &detector));
CHECK_FALSE(trait.moveConstruct(ptr, &detector));
CHECK_FALSE(trait.hasDefaultConstruct());
CHECK_FALSE(trait.hasCopyConstruct());
CHECK_FALSE(trait.hasMoveConstruct());

operator delete(ptr);
}
Expand All @@ -61,7 +61,8 @@ TEST_CASE("reflection::ConstructibleTrait")
auto* ptr = operator new(sizeof(SimpleConstructible));

auto trait = ConstructibleTrait::typed<SimpleConstructible>().withDefaultConstructor().build();
REQUIRE(trait.defaultConstruct(ptr));
REQUIRE(trait.hasDefaultConstruct());
trait.defaultConstruct(ptr);

auto* simple = static_cast<SimpleConstructible*>(ptr);
CHECK(simple->value == SimpleConstructible::DEFAULT);
Expand All @@ -77,7 +78,8 @@ TEST_CASE("reflection::ConstructibleTrait")
auto trait = ConstructibleTrait::typed<SimpleConstructible>().withCopyConstructor().build();
SimpleConstructible copied{};
copied.value = 1;
REQUIRE(trait.copyConstruct(ptr, &copied));
REQUIRE(trait.hasCopyConstruct());
trait.copyConstruct(ptr, &copied);

auto* simple = static_cast<SimpleConstructible*>(ptr);
CHECK(simple->value == copied.value);
Expand All @@ -97,7 +99,8 @@ TEST_CASE("reflection::ConstructibleTrait")
// the flag is not set when 'moved' is destructed.
{
DetectDestructor moved{&destroyed};
REQUIRE(trait.moveConstruct(ptr, &moved));
REQUIRE(trait.hasMoveConstruct());
trait.moveConstruct(ptr, &moved);
REQUIRE_FALSE(destroyed);
}

Expand Down
9 changes: 6 additions & 3 deletions core/tests/reflection/traits/constructible.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ static void testDefaultConstructible()
auto& constructible = type.get<ConstructibleTrait>();

auto* instance = operator new(constructible.size());
REQUIRE(constructible.defaultConstruct(instance));
REQUIRE(constructible.hasDefaultConstruct());
constructible.defaultConstruct(instance);

if constexpr (std::equality_comparable<T>)
{
Expand All @@ -57,7 +58,8 @@ static void testCopyConstructible(const T& valueToCopy)
auto& constructible = type.get<ConstructibleTrait>();

auto* instance = operator new(constructible.size());
REQUIRE(constructible.copyConstruct(instance, &valueToCopy));
REQUIRE(constructible.hasCopyConstruct());
constructible.copyConstruct(instance, &valueToCopy);

if constexpr (std::equality_comparable<T>)
{
Expand All @@ -79,7 +81,8 @@ static void testMoveConstructible(T& valueToMove)
auto& constructible = type.get<ConstructibleTrait>();

auto* instance = operator new(constructible.size());
REQUIRE(constructible.moveConstruct(instance, &valueToMove));
REQUIRE(constructible.hasMoveConstruct());
constructible.moveConstruct(instance, &valueToMove);

constructible.destruct(instance);
operator delete(instance);
Expand Down

0 comments on commit 1b6d0db

Please sign in to comment.