Class poly

Synopsis

#include <src/entt/poly/poly.hpp>

template<typename Concept>
class poly: private Concept::template type<poly_base<poly<Concept>>>

Description

Static polymorphism made simple and within everyone's reach.

Static polymorphism is a very powerful tool in C++, albeit sometimes cumbersome to obtain.
This class aims to make it simple and easy to use.

Note
Both deduced and defined static virtual tables are supported.
Moreover, the poly class template also works with unmanaged objects.
Template Parameters

Concept - Concept descriptor.

Mentioned in

Inheritance

Ancestors: Concept::template type< poly_base< poly< Concept > > >

Methods

poly overloadDefault constructor.
poly overloadConstructs a poly by directly initializing the new object.
poly overloadConstructs a poly that holds an unmanaged object.
poly overloadConstructs a poly from a given value.
poly overloadCopy constructor.
poly overloadMove constructor.
data overloadReturns an opaque pointer to the contained instance.
emplaceReplaces the contained object by creating a new instance directly.
operator boolReturns false if a poly is empty, true otherwise.
operator-> overloadReturns a pointer to the underlying concept.
operator=Assignment operator.
typeReturns the type of the contained object.

Source

Lines 175-338 in src/entt/poly/poly.hpp.

template<typename Concept>
class poly: private Concept::template type<poly_base<poly<Concept>>> {
    /*! @brief A poly base is allowed to snoop into a poly object. */
    friend struct poly_base<poly<Concept>>;

    using vtable_type = typename poly_vtable<Concept>::type;

public:
    /*! @brief Concept type. */
    using concept_type = typename Concept::template type<poly_base<poly<Concept>>>;

    /*! @brief Default constructor. */
    poly() ENTT_NOEXCEPT
        : storage{},
          vtable{}
    {}

    /**
     * @brief Constructs a poly by directly initializing the new object.
     * @tparam Type Type of object to use to initialize the poly.
     * @tparam Args Types of arguments to use to construct the new instance.
     * @param args Parameters to use to construct the instance.
     */
    template<typename Type, typename... Args>
    explicit poly(std::in_place_type_t<Type>, Args &&... args)
        : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
          vtable{poly_vtable<Concept>::template instance<std::remove_const_t<std::remove_reference_t<Type>>>()}
    {}

    /**
     * @brief Constructs a poly that holds an unmanaged object.
     * @tparam Type Type of object to use to initialize the poly.
     * @param value An instance of an object to use to initialize the poly.
     */
    template<typename Type>
    poly(std::reference_wrapper<Type> value)
        : poly{std::in_place_type<Type &>, &value.get()}
    {}

    /**
     * @brief Constructs a poly from a given value.
     * @tparam Type Type of object to use to initialize the poly.
     * @param value An instance of an object to use to initialize the poly.
     */
    template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, poly>>>
    poly(Type &&value) ENTT_NOEXCEPT
        : poly{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)}
    {}

    /**
     * @brief Copy constructor.
     * @param other The instance to copy from.
     */
    poly(const poly &other) = default;

    /**
     * @brief Move constructor.
     * @param other The instance to move from.
     */
    poly(poly &&other) ENTT_NOEXCEPT
        : poly{}
    {
        swap(*this, other);
    }

    /**
     * @brief Assignment operator.
     * @param other The instance to assign from.
     * @return This poly object.
     */
    poly & operator=(poly other) {
        swap(other, *this);
        return *this;
    }

    /**
     * @brief Returns the type of the contained object.
     * @return The type of the contained object, if any.
     */
    [[nodiscard]] type_info type() const ENTT_NOEXCEPT {
        return storage.type();
    }

    /**
     * @brief Returns an opaque pointer to the contained instance.
     * @return An opaque pointer the contained instance, if any.
     */
    [[nodiscard]] const void * data() const ENTT_NOEXCEPT {
        return storage.data();
    }

    /*! @copydoc data */
    [[nodiscard]] void * data() ENTT_NOEXCEPT {
        return storage.data();
    }

    /**
     * @brief Replaces the contained object by creating a new instance directly.
     * @tparam Type Type of object to use to initialize the poly.
     * @tparam Args Types of arguments to use to construct the new instance.
     * @param args Parameters to use to construct the instance.
     */
    template<typename Type, typename... Args>
    void emplace(Args &&... args) {
        storage.emplace<Type>(std::forward<Args>(args)...);
        vtable = poly_vtable<Concept>::template instance<Type>();
    }

    /**
     * @brief Returns false if a poly is empty, true otherwise.
     * @return False if the poly is empty, true otherwise.
     */
    [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
        return !(vtable == nullptr);
    }

    /**
     * @brief Returns a pointer to the underlying concept.
     * @return A pointer to the underlying concept.
     */
    [[nodiscard]] concept_type * operator->() ENTT_NOEXCEPT {
        return this;
    }

    /*! @copydoc operator-> */
    [[nodiscard]] const concept_type * operator->() const ENTT_NOEXCEPT {
        return this;
    }

    /**
     * @brief Swaps two poly objects.
     * @param lhs A valid poly object.
     * @param rhs A valid poly object.
     */
    friend void swap(poly &lhs, poly &rhs) {
        using std::swap;
        swap(lhs.storage, rhs.storage);
        swap(lhs.vtable, rhs.vtable);
    }

    /**
     * @brief Aliasing constructor.
     * @param other A reference to an object that isn't necessarily initialized.
     * @return A poly that shares a reference to an unmanaged object.
     */
    [[nodiscard]] friend poly as_ref(poly &other) ENTT_NOEXCEPT {
        poly ref;
        ref.storage = as_ref(other.storage);
        ref.vtable = other.vtable;
        return ref;
    }

    /*! @copydoc as_ref */
    [[nodiscard]] friend poly as_ref(const poly &other) ENTT_NOEXCEPT {
        poly ref;
        ref.storage = as_ref(other.storage);
        ref.vtable = other.vtable;
        return ref;
    }

private:
    any storage;
    const vtable_type *vtable;
};





Add Discussion

Log in to comment