/// @file dpf/emplace.hpp /// @brief Defines various template structures for efficient emplacement of /// `dpf::dpf_key` objects. /// @details Provides specialized template structures for the in-place /// construction ("emplacing") of `dpf::dpf_key` objects into different /// types of pre-allocated storage including smart pointers /// (`std::unique_ptr` and `std::shared_ptr`), `std::optional`, /// `std::variant`, raw pointers, and `std::reference_wrapper`s, as /// well as containers that support `emplace_back`. The goal is to /// facilitate efficient construction and storage of `dpf::dpf_key` /// objects received from a dealer over a socket. /// /// The emplacement functionalities are specialized for different /// storage types to handle their unique construction requirements. /// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors) /// @license Released under a GNU General Public v2.0 (GPLv2) license; /// see [LICENSE.md](@ref license) for details. #ifndef LIBDPF_INCLUDE_DPF_EMPLACE_HPP__ #define LIBDPF_INCLUDE_DPF_EMPLACE_HPP__ #include "hedley/hedley.h" #include #include #include #include namespace dpf { namespace utils { /// @brief Emplaces a `dpf::dpf_key` object into the specified, pre-allocated memory. /// @tparam DpfKey The concrete specialization of `dpf::dpf_key` to construct. /// @param storage Reference to the container where the `dpf::dpf_key` object will be emplaced. /// @param root The root node used by the `dpf::dpf_key`. /// @param correction_words Correction words array for the `dpf::dpf_key`. /// @param correction_advice Correction advice array for the `dpf::dpf_key`. /// @param leaves Leaf-node tuple for the `dpf::dpf_key`. /// @param beavers Beaver tuple for the `dpf::dpf_key`. /// @param offset_share The offset share (default: `0`). /// @defgroup EmplaceFunctions Emplace Functions /// @brief Group of functions for emplacing `dpf::dpf_key` objects into /// pre-allocated memory. /// @{ template struct dpf_emplacer { using dpf_key = DpfKey; using interior_node = typename DpfKey::interior_node; using correction_words_array = typename DpfKey::correction_words_array; using correction_advice_array = typename DpfKey::correction_advice_array; using leaf_tuple = typename DpfKey::leaf_tuple; using beaver_tuple = typename DpfKey::beaver_tuple; using input_type = typename DpfKey::input_type; /// @brief Generic version is intentionally left undefined. static auto emplace(T & storage, const interior_node & root, const correction_words_array & correction_words, const correction_advice_array & correction_advice, const leaf_tuple & leaves, const beaver_tuple & beavers, const input_type & offset_share); }; /// @brief Specialization for `std::unique_ptr`. template struct dpf_emplacer> { using dpf_key = DpfKey; using interior_node = typename DpfKey::interior_node; using correction_words_array = typename DpfKey::correction_words_array; using correction_advice_array = typename DpfKey::correction_advice_array; using leaf_tuple = typename DpfKey::leaf_tuple; using beaver_tuple = typename DpfKey::beaver_tuple; using input_type = typename DpfKey::input_type; HEDLEY_ALWAYS_INLINE static auto emplace( std::unique_ptr & storage, const interior_node & root, const correction_words_array & correction_words, const correction_advice_array & correction_advice, const leaf_tuple & leaves, const beaver_tuple & beavers, const input_type & offset_share) { storage.reset(new DpfKey(root, correction_words, correction_advice, leaves, beavers, offset_share)); } }; template struct dpf_emplacer> { using dpf_key = DpfKey; using interior_node = typename DpfKey::interior_node; using correction_words_array = typename DpfKey::correction_words_array; using correction_advice_array = typename DpfKey::correction_advice_array; using leaf_tuple = typename DpfKey::leaf_tuple; using beaver_tuple = typename DpfKey::beaver_tuple; using input_type = typename DpfKey::input_type; HEDLEY_ALWAYS_INLINE static auto emplace( std::shared_ptr & storage, const interior_node & root, const correction_words_array & correction_words, const correction_advice_array & correction_advice, const leaf_tuple & leaves, const beaver_tuple & beavers, const input_type & offset_share) { storage = std::make_shared(root, correction_words, correction_advice, leaves, beavers, offset_share); } }; template struct dpf_emplacer> { using dpf_key = DpfKey; using interior_node = typename DpfKey::interior_node; using correction_words_array = typename DpfKey::correction_words_array; using correction_advice_array = typename DpfKey::correction_advice_array; using leaf_tuple = typename DpfKey::leaf_tuple; using beaver_tuple = typename DpfKey::beaver_tuple; using input_type = typename DpfKey::input_type; HEDLEY_ALWAYS_INLINE static auto emplace( std::optional & storage, const interior_node & root, const correction_words_array & correction_words, const correction_advice_array & correction_advice, const leaf_tuple & leaves, const beaver_tuple & beavers, const input_type & offset_share) { storage.emplace(root, correction_words, correction_advice, leaves, beavers, offset_share); } }; template struct dpf_emplacer> { using dpf_key = DpfKey; using interior_node = typename DpfKey::interior_node; using correction_words_array = typename DpfKey::correction_words_array; using correction_advice_array = typename DpfKey::correction_advice_array; using leaf_tuple = typename DpfKey::leaf_tuple; using beaver_tuple = typename DpfKey::beaver_tuple; using input_type = typename DpfKey::input_type; HEDLEY_ALWAYS_INLINE static auto emplace( std::variant & storage, const interior_node & root, const correction_words_array & correction_words, const correction_advice_array & correction_advice, const leaf_tuple & leaves, const beaver_tuple & beavers, const input_type & offset_share) { storage.template emplace(root, correction_words, correction_advice, leaves, beavers, offset_share); } }; template struct dpf_emplacer { using dpf_key = DpfKey; using interior_node = typename DpfKey::interior_node; using correction_words_array = typename DpfKey::correction_words_array; using correction_advice_array = typename DpfKey::correction_advice_array; using leaf_tuple = typename DpfKey::leaf_tuple; using beaver_tuple = typename DpfKey::beaver_tuple; using input_type = typename DpfKey::input_type; HEDLEY_ALWAYS_INLINE static auto emplace( DpfKey * storage, const interior_node & root, const correction_words_array & correction_words, const correction_advice_array & correction_advice, const leaf_tuple & leaves, const beaver_tuple & beavers, const input_type & offset_share) { ::new (storage) DpfKey(root, correction_words, correction_advice, leaves, beavers, offset_share); } }; template struct dpf_emplacer> { using dpf_key = DpfKey; using interior_node = typename DpfKey::interior_node; using correction_words_array = typename DpfKey::correction_words_array; using correction_advice_array = typename DpfKey::correction_advice_array; using leaf_tuple = typename DpfKey::leaf_tuple; using beaver_tuple = typename DpfKey::beaver_tuple; using input_type = typename DpfKey::input_type; HEDLEY_ALWAYS_INLINE static auto emplace( std::reference_wrapper storage, const interior_node & root, const correction_words_array & correction_words, const correction_advice_array & correction_advice, const leaf_tuple & leaves, const beaver_tuple & beavers, const input_type & offset_share) { storage.get().~DpfKey(); ::new (&storage.get()) DpfKey(root, correction_words, correction_advice, leaves, beavers, offset_share); } }; /// @} template struct dpf_back_emplacer { using dpf_key = DpfKey; using interior_node = typename DpfKey::interior_node; using correction_words_array = typename DpfKey::correction_words_array; using correction_advice_array = typename DpfKey::correction_advice_array; using leaf_tuple = typename DpfKey::leaf_tuple; using beaver_tuple = typename DpfKey::beaver_tuple; using input_type = typename DpfKey::input_type; static auto emplace_back(ContainerT & storage, const interior_node & root, const correction_words_array & correction_words, const correction_advice_array & correction_advice, const leaf_tuple & leaves, const beaver_tuple & beavers, const input_type & offset_share) { storage.emplace_back(root, correction_words, correction_advice, leaves, beavers, offset_share); } }; } // namespace utils } // namespace std #endif // LIBDPF_INCLUDE_DPF_EMPLACE_HPP__