#pragma once #include "BLEAPI.hpp" #include #include #include #include BEGIN_CS_NAMESPACE struct BLEDataGenerator::Iface { virtual ~Iface() = default; virtual BLEDataView next() = 0; virtual Iface *move_into(void *storage) noexcept = 0; Iface(const Iface &) = delete; Iface &operator=(const Iface &) = delete; protected: Iface() = default; Iface(Iface &&) = default; }; template struct BLEDataGenerator::Impl : Iface { T inst; template Impl(Args &&...args) : inst {std::forward(args)...} {} #if __cplusplus >= 201703L BLEDataView next() override { return std::invoke(inst); } #else BLEDataView next() override { return inst(); } #endif Iface *move_into(void *storage) noexcept override { return new (storage) Impl {std::move(*this)}; } }; inline BLEDataView BLEDataGenerator::operator()() { assert(instance); return instance->next(); } inline void BLEDataGenerator::clear() { #if __cplusplus >= 201402 if (auto *inst = std::exchange(instance, nullptr)) inst->~Iface(); #else if (instance) instance->~Iface(); instance = nullptr; #endif } template BLEDataGenerator::BLEDataGenerator(compat::in_place_type_t, Args &&...args) { static_assert(sizeof(Impl) <= sizeof(storage), ""); static_assert(alignof(Impl) <= alignof(buffer_align_t), ""); instance = new (storage) Impl {std::forward(args)...}; } template BLEDataGenerator::BLEDataGenerator(compat::in_place_t, T &&t) : BLEDataGenerator( compat::in_place_type::type>, std::forward(t)) {} inline BLEDataGenerator::BLEDataGenerator(BLEDataGenerator &&other) noexcept { if (other.instance) { this->instance = other.instance->move_into(this->storage); other.clear(); } } inline BLEDataGenerator & BLEDataGenerator::operator=(BLEDataGenerator &&other) noexcept { clear(); if (other.instance) { this->instance = other.instance->move_into(this->storage); other.clear(); } return *this; } END_CS_NAMESPACE