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, thepoly
class template also works with unmanaged objects. - Template Parameters
Concept
- Concept descriptor.
Mentioned in
- Entity Component System / Meet the runtime
- Poly / Crash Course: poly
- Poly / Introduction
- Poly / Inheritance
- Poly / Static polymorphism in the wild
Inheritance
Ancestors: Concept::template type< poly_base< poly< Concept > > >
Methods
poly overload | Default constructor. | |
poly overload | Constructs a poly by directly initializing the new object. | |
poly overload | Constructs a poly that holds an unmanaged object. | |
poly overload | Constructs a poly from a given value. | |
poly overload | Copy constructor. | |
poly overload | Move constructor. | |
data overload | Returns an opaque pointer to the contained instance. | |
emplace | Replaces the contained object by creating a new instance directly. | |
operator bool | Returns false if a poly is empty, true otherwise. | |
operator-> overload | Returns a pointer to the underlying concept. | |
operator= | Assignment operator. | |
type | Returns 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;
};