Class poly_vtable

Synopsis

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

template<typename Concept, std::size_t Len, std::size_t Align>
class poly_vtable

Description

Static virtual table factory.

Template Parameters

Concept - Concept descriptor.

Len - Size of the storage reserved for the small buffer optimization.

Align - Alignment requirement.

Mentioned in

Methods

instanceReturns a static virtual table for a specific concept and type.

Source

Lines 47-122 in src/entt/poly/poly.hpp.

template<typename Concept, std::size_t Len, std::size_t Align>
class poly_vtable {
    using inspector = typename Concept::template type<poly_inspector>;

    template<typename Ret, typename... Args>
    static auto vtable_entry(Ret (*)(inspector &, Args...)) -> Ret (*)(basic_any<Len, Align> &, Args...);

    template<typename Ret, typename... Args>
    static auto vtable_entry(Ret (*)(const inspector &, Args...)) -> Ret (*)(const basic_any<Len, Align> &, Args...);

    template<typename Ret, typename... Args>
    static auto vtable_entry(Ret (*)(Args...)) -> Ret (*)(const basic_any<Len, Align> &, Args...);

    template<typename Ret, typename... Args>
    static auto vtable_entry(Ret (inspector::*)(Args...)) -> Ret (*)(basic_any<Len, Align> &, Args...);

    template<typename Ret, typename... Args>
    static auto vtable_entry(Ret (inspector::*)(Args...) const) -> Ret (*)(const basic_any<Len, Align> &, Args...);

    template<auto... Candidate>
    static auto make_vtable(value_list<Candidate...>) ENTT_NOEXCEPT
        -> decltype(std::make_tuple(vtable_entry(Candidate)...));

    template<typename... Func>
    [[nodiscard]] static constexpr auto make_vtable(type_list<Func...>) ENTT_NOEXCEPT {
        if constexpr(sizeof...(Func) == 0u) {
            return decltype(make_vtable(typename Concept::template impl<inspector>{})){};
        } else if constexpr((std::is_function_v<Func> && ...)) {
            return decltype(std::make_tuple(vtable_entry(std::declval<Func inspector::*>())...)){};
        }
    }

    template<typename Type, auto Candidate, typename Ret, typename Any, typename... Args>
    static void fill_vtable_entry(Ret (*&entry)(Any &, Args...)) ENTT_NOEXCEPT {
        if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
            entry = +[](Any &, Args... args) -> Ret {
                return std::invoke(Candidate, std::forward<Args>(args)...);
            };
        } else {
            entry = +[](Any &instance, Args... args) -> Ret {
                return static_cast<Ret>(std::invoke(Candidate, any_cast<constness_as_t<Type, Any> &>(instance), std::forward<Args>(args)...));
            };
        }
    }

    template<typename Type, auto... Index>
    [[nodiscard]] static auto fill_vtable(std::index_sequence<Index...>) ENTT_NOEXCEPT {
        vtable_type impl{};
        (fill_vtable_entry<Type, value_list_element_v<Index, typename Concept::template impl<Type>>>(std::get<Index>(impl)), ...);
        return impl;
    }

    using vtable_type = decltype(make_vtable(Concept{}));
    static constexpr bool is_mono_v = std::tuple_size_v<vtable_type> == 1u;

public:
    /*! @brief Virtual table type. */
    using type = std::conditional_t<is_mono_v, std::tuple_element_t<0u, vtable_type>, const vtable_type *>;

    /**
     * @brief Returns a static virtual table for a specific concept and type.
     * @tparam Type The type for which to generate the virtual table.
     * @return A static virtual table for the given concept and type.
     */
    template<typename Type>
    [[nodiscard]] static type instance() ENTT_NOEXCEPT {
        static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Type differs from its decayed form");
        static const vtable_type vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{});

        if constexpr(is_mono_v) {
            return std::get<0>(vtable);
        } else {
            return &vtable;
        }
    }
};





Add Discussion

Log in to comment