1#ifndef ENTT_POLY_POLY_HPP
2#define ENTT_POLY_POLY_HPP
9#include "../core/any.hpp"
10#include "../core/type_info.hpp"
11#include "../core/type_traits.hpp"
22 template<
typename Type>
23 operator Type &&()
const;
32 template<std::size_t Member,
typename... Args>
36 template<std::size_t Member,
typename... Args>
46template<
typename Concept, std::
size_t Len, std::
size_t Align>
50 template<
typename Ret,
typename... Args>
53 template<
typename Ret,
typename... Args>
54 static auto vtable_entry(Ret (*)(
const inspector &, Args...)) -> Ret (*)(
const basic_any<Len, Align> &, Args...);
56 template<
typename Ret,
typename... Args>
59 template<
typename Ret,
typename... Args>
62 template<
typename Ret,
typename... Args>
63 static auto vtable_entry(Ret (inspector::*)(Args...)
const) -> Ret (*)(
const basic_any<Len, Align> &, Args...);
65 template<
auto... Candidate>
67 ->
decltype(std::make_tuple(vtable_entry(Candidate)...));
69 template<
typename... Func>
71 if constexpr(
sizeof...(Func) == 0u) {
72 return decltype(make_vtable(
typename Concept::template impl<inspector>{})){};
73 }
else if constexpr((std::is_function_v<Func> && ...)) {
74 return decltype(std::make_tuple(vtable_entry(std::declval<Func inspector::*>())...)){};
78 template<
typename Type,
auto Candidate,
typename Ret,
typename Any,
typename... Args>
79 static void fill_vtable_entry(Ret (*&entry)(Any &, Args...))
noexcept {
80 if constexpr(std::is_invocable_r_v<Ret,
decltype(Candidate), Args...>) {
81 entry = +[](Any &, Args... args) -> Ret {
82 return std::invoke(Candidate, std::forward<Args>(args)...);
85 entry = +[](Any &
instance, Args... args) -> Ret {
91 template<
typename Type,
auto... Index>
92 [[nodiscard]]
static auto fill_vtable(std::index_sequence<Index...>)
noexcept {
94 (fill_vtable_entry<Type, value_list_element_v<Index, typename Concept::template impl<Type>>>(std::get<Index>(impl)), ...);
98 using vtable_type =
decltype(make_vtable(Concept{}));
99 static constexpr bool is_mono_v = std::tuple_size_v<vtable_type> == 1u;
103 using type = std::conditional_t<is_mono_v, std::tuple_element_t<0u, vtable_type>,
const vtable_type *>;
110 template<
typename Type>
112 static_assert(std::is_same_v<Type, std::decay_t<Type>>,
"Type differs from its decayed form");
113 static const vtable_type vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{});
115 if constexpr(is_mono_v) {
116 return std::get<0>(vtable);
127template<
typename Poly>
137 template<std::size_t Member,
typename... Args>
139 const auto &
poly =
static_cast<const Poly &
>(self);
141 if constexpr(std::is_function_v<std::remove_pointer_t<
decltype(
poly.vtable)>>) {
142 return poly.vtable(
poly.storage, std::forward<Args>(args)...);
144 return std::get<Member>(*
poly.vtable)(
poly.storage, std::forward<Args>(args)...);
149 template<std::size_t Member,
typename... Args>
151 auto &
poly =
static_cast<Poly &
>(self);
153 if constexpr(std::is_function_v<std::remove_pointer_t<
decltype(
poly.vtable)>>) {
154 static_assert(Member == 0u,
"Unknown member");
155 return poly.vtable(
poly.storage, std::forward<Args>(args)...);
157 return std::get<Member>(*
poly.vtable)(
poly.storage, std::forward<Args>(args)...);
171template<std::size_t Member,
typename Poly,
typename... Args>
173 return std::forward<Poly>(self).template invoke<Member>(self, std::forward<Args>(args)...);
191template<
typename Concept, std::
size_t Len, std::
size_t Align>
192class basic_poly:
private Concept::template type<poly_base<basic_poly<Concept, Len, Align>>> {
197 using concept_type =
typename Concept::template type<poly_base<basic_poly>>;
212 template<
typename Type,
typename... Args>
213 explicit basic_poly(std::in_place_type_t<Type>, Args &&...args)
214 :
storage{std::in_place_type<Type>, std::forward<Args>(args)...},
215 vtable{
poly_vtable<Concept, Len, Align>::template instance<std::remove_cv_t<std::remove_reference_t<Type>>>()} {}
222 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, basic_poly>>>
224 :
basic_poly{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)} {}
238 [[nodiscard]]
const void *
data() const noexcept {
243 [[nodiscard]]
void *
data() noexcept {
253 template<
typename Type,
typename... Args>
255 storage.template emplace<Type>(std::forward<Args>(args)...);
269 [[nodiscard]]
explicit operator bool() const noexcept {
270 return static_cast<bool>(
storage);
A SBO friendly, type-safe container for single values of any type.
Static polymorphism made simple and within everyone's reach.
const type_info & type() const noexcept
Returns the object type if any, type_id<void>() otherwise.
basic_poly as_ref() noexcept
Aliasing constructor.
void * data() noexcept
Returns an opaque pointer to the contained instance.
void reset()
Destroys contained object.
concept_type * operator->() noexcept
Returns a pointer to the underlying concept.
void emplace(Args &&...args)
Replaces the contained object by creating a new instance directly.
basic_poly as_ref() const noexcept
Aliasing constructor.
const concept_type * operator->() const noexcept
Returns a pointer to the underlying concept.
basic_poly(Type &&value) noexcept
Constructs a poly from a given value.
typename poly_vtable< Concept, Len, Align >::type vtable_type
Virtual table type.
typename Concept::template type< poly_base< basic_poly > > concept_type
Concept type.
basic_poly() noexcept
Default constructor.
basic_poly(std::in_place_type_t< Type >, Args &&...args)
Constructs a poly by directly initializing the new object.
const void * data() const noexcept
Returns an opaque pointer to the contained instance.
pointer data() const noexcept
Direct access to the internal packed array.
const type_info & type() const noexcept
Returned value type, if any.
Basic storage implementation.
Static virtual table factory.
std::conditional_t< is_mono_v, std::tuple_element_t< 0u, vtable_type >, const vtable_type * > type
Virtual table type.
static type instance() noexcept
Returns a static virtual table for a specific concept and type.
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
decltype(auto) poly_call(Poly &&self, Args &&...args)
Shortcut for calling poly_base<Type>::invoke.
Type any_cast(const basic_any< Len, Align > &data) noexcept
Performs type-safe access to the contained object.
@ ref
Aliasing mode, the object points to a non-const element.
Poly base class used to inject functionalities into concepts.
decltype(auto) invoke(const poly_base &self, Args &&...args) const
Invokes a function from the static virtual table.
decltype(auto) invoke(poly_base &self, Args &&...args)
Invokes a function from the static virtual table.
Inspector class used to infer the type of the virtual table.
poly_inspector invoke(Args &&...args) const
Dummy invocation function (definition only).
poly_inspector invoke(Args &&...args)
Dummy invocation function (definition only).
Implementation specific information about a type.
A class to use to push around lists of types, nothing more.
A class to use to push around lists of constant values, nothing more.