poly: added configurable sbo size (0 -> forced dyn)
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
* [Fullfill a concept](#fullfill-a-concept)
|
||||
* [Inheritance](#inheritance)
|
||||
* [Static polymorphism in the wild](#static-polymorphism-in-the-wild)
|
||||
* [Configurable storage size](#configurable-storage-size)
|
||||
<!--
|
||||
@endcond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
@@ -236,7 +237,7 @@ For a deduced concept, inheritance is achieved in a few steps:
|
||||
```cpp
|
||||
struct DrawableAndErasable: entt::type_list<> {
|
||||
template<typename Base>
|
||||
struct type: typename Drawable::type<Base> {
|
||||
struct type: typename Drawable::template type<Base> {
|
||||
static constexpr auto base = std::tuple_size_v<typename entt::poly_vtable<Drawable>::type>;
|
||||
void erase() { entt::poly_call<base + 0>(*this); }
|
||||
};
|
||||
@@ -336,3 +337,22 @@ This allows users to decouple the API of the wrapper from that of the concept.
|
||||
Therefore, where `instance.data()` will invoke the `data` member function of the
|
||||
poly object, `instance->data()` will map directly to the functionality exposed
|
||||
by the underlying concept.
|
||||
|
||||
# Configurable storage size
|
||||
|
||||
Under the hood, the `poly` class template makes use of `entt::any`. Therefore,
|
||||
it can take advantage of the possibility of defining at compile-time the size of
|
||||
the storage suitable for the small buffer optimization.<br/>
|
||||
To do this, it will be sufficient to provide the desired size as a second
|
||||
template parameter:
|
||||
|
||||
```cpp
|
||||
entt::poly<Drawable, sizeof(double[4])>
|
||||
```
|
||||
|
||||
The default value is `sizeof(double[2])`, which seems like a good compromise
|
||||
between a buffer that is too large and one unable to hold anything larger than
|
||||
an integer.<br/>
|
||||
It's worth noting that providing a size of 0 (which is an accepted value in all
|
||||
respects) will force the system to dynamically allocate the contained objects in
|
||||
all cases.
|
||||
|
||||
@@ -171,17 +171,18 @@ decltype(auto) poly_call(Poly &&self, Args &&... args) {
|
||||
* Moreover, the `poly` class template also works with unmanaged objects.
|
||||
*
|
||||
* @tparam Concept Concept descriptor.
|
||||
* @tparam Len Size of the storage reserved for the small buffer optimization.
|
||||
*/
|
||||
template<typename Concept>
|
||||
class poly: private Concept::template type<poly_base<poly<Concept>>> {
|
||||
template<typename Concept, std::size_t Len = sizeof(double[2])>
|
||||
class poly: private Concept::template type<poly_base<poly<Concept, Len>>> {
|
||||
/*! @brief A poly base is allowed to snoop into a poly object. */
|
||||
friend struct poly_base<poly<Concept>>;
|
||||
friend struct poly_base<poly>;
|
||||
|
||||
using vtable_type = typename poly_vtable<Concept>::type;
|
||||
|
||||
public:
|
||||
/*! @brief Concept type. */
|
||||
using concept_type = typename Concept::template type<poly_base<poly<Concept>>>;
|
||||
using concept_type = typename Concept::template type<poly_base<poly>>;
|
||||
|
||||
/*! @brief Default constructor. */
|
||||
poly() ENTT_NOEXCEPT
|
||||
@@ -336,7 +337,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
any storage;
|
||||
basic_any<Len> storage;
|
||||
const vtable_type *vtable;
|
||||
};
|
||||
|
||||
|
||||
@@ -208,3 +208,17 @@ TEST(PolyDeduced, AsRef) {
|
||||
ASSERT_NE(ref.data(), nullptr);
|
||||
ASSERT_NE(cref.data(), nullptr);
|
||||
}
|
||||
|
||||
TEST(PolyDeduced, SBOVsZeroedSBOSize) {
|
||||
entt::poly<Deduced> sbo{impl{}};
|
||||
const auto broken = sbo.data();
|
||||
entt::poly<Deduced> other = std::move(sbo);
|
||||
|
||||
ASSERT_NE(broken, other.data());
|
||||
|
||||
entt::poly<Deduced, 0u> dyn{impl{}};
|
||||
const auto valid = dyn.data();
|
||||
entt::poly<Deduced, 0u> same = std::move(dyn);
|
||||
|
||||
ASSERT_EQ(valid, same.data());
|
||||
}
|
||||
|
||||
@@ -214,3 +214,17 @@ TEST(PolyDefined, AsRef) {
|
||||
ASSERT_NE(ref.data(), nullptr);
|
||||
ASSERT_NE(cref.data(), nullptr);
|
||||
}
|
||||
|
||||
TEST(PolyDefined, SBOVsZeroedSBOSize) {
|
||||
entt::poly<Defined> sbo{impl{}};
|
||||
const auto broken = sbo.data();
|
||||
entt::poly<Defined> other = std::move(sbo);
|
||||
|
||||
ASSERT_NE(broken, other.data());
|
||||
|
||||
entt::poly<Defined, 0u> dyn{impl{}};
|
||||
const auto valid = dyn.data();
|
||||
entt::poly<Defined, 0u> same = std::move(dyn);
|
||||
|
||||
ASSERT_EQ(valid, same.data());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user