// // Created by erki on 24/10/23. // #pragma once #include #include #include #include namespace cpptick { template concept TrivialClass = std::is_trivial_v && std::is_trivially_destructible_v; template concept CopyableClass = !TrivialClass && std::copy_constructible; template concept SlotArgument = TrivialClass || CopyableClass; struct ArgStorage { std::array buffer; std::array pointer_buffer; std::array::iterator pointer_buffer_head; std::size_t space_remaining; ArgStorage() = default; ArgStorage(const ArgStorage&) = default; ArgStorage(ArgStorage&&) = default; void reset() { space_remaining = buffer.size(); pointer_buffer_head = pointer_buffer.begin(); *pointer_buffer_head = buffer.data(); } template void pushArg(T&& arg) { if (pointer_buffer_head == pointer_buffer.end() || space_remaining == 0) std::exit(1); void* memory_location = *pointer_buffer_head; if (std::align(alignof(T), sizeof(T), memory_location, space_remaining) == nullptr) std::exit(2); std::memcpy(memory_location, &arg, sizeof(T)); pointer_buffer_head++; if (pointer_buffer_head != pointer_buffer.end()) { *pointer_buffer_head = (char*)memory_location + sizeof(T); space_remaining -= sizeof(T); } } template void pushArg(T&& arg) { if (pointer_buffer_head == pointer_buffer.end() || space_remaining == 0) std::exit(1); void* memory_location = *pointer_buffer_head; if (std::align(alignof(T), sizeof(T), memory_location, space_remaining) == nullptr) std::exit(2); new (memory_location) T{arg}; pointer_buffer_head++; if (pointer_buffer_head != pointer_buffer.end()) { *pointer_buffer_head = (char*)memory_location + sizeof(T); space_remaining -= sizeof(T); } } template void cleanUp(const std::size_t) { } template void cleanUp(const std::size_t index) { T* item = reinterpret_cast(pointer_buffer[index]); item->~T(); } template void cleanUp(std::index_sequence) { (cleanUp(Is), ...); } template void cleanUp() { cleanUp(std::make_index_sequence{}); } template T& at(const std::size_t idx) { return *((T*)pointer_buffer[idx]); } template const T& at(const std::size_t idx) const { return *((T*)pointer_buffer[idx]); } }; }