mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-05-10 19:21:42 +00:00
feat(bindless): Backport inplace_vector for constexpr
This commit is contained in:
parent
93816ef4ab
commit
602f571c1d
1 changed files with 93 additions and 0 deletions
93
lsfg-vk-backend/src/modules/pipeline/signature/helpers.hpp
Normal file
93
lsfg-vk-backend/src/modules/pipeline/signature/helpers.hpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace lsfgvk::pipeline {
|
||||
|
||||
/// C++26 backported inplace_vector
|
||||
template<typename T, size_t N>
|
||||
class inplace_vector {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
||||
public:
|
||||
// Constructors
|
||||
constexpr inplace_vector() = default;
|
||||
constexpr inplace_vector(std::initializer_list<T> init) {
|
||||
if (init.size() > N) throw std::bad_alloc();
|
||||
for (auto& elem : init)
|
||||
this->m_data.at(this->m_size++) = elem;
|
||||
}
|
||||
constexpr inplace_vector(const std::vector<T>& vec) {
|
||||
if (vec.size() > N) throw std::bad_alloc();
|
||||
for (const auto& elem : vec)
|
||||
this->m_data.at(this->m_size++) = elem;
|
||||
}
|
||||
|
||||
// Appending elements
|
||||
constexpr void push_back(const T& value) {
|
||||
if (this->m_size >= N) throw std::bad_alloc();
|
||||
this->m_data.at(this->m_size++) = value;
|
||||
}
|
||||
constexpr void push_back(T&& value) {
|
||||
if (this->m_size >= N) throw std::bad_alloc();
|
||||
this->m_data.at(this->m_size++) = std::move(value);
|
||||
}
|
||||
template<typename... Args>
|
||||
constexpr T& emplace_back(Args&&... args) {
|
||||
if (this->m_size >= N) throw std::bad_alloc();
|
||||
this->m_data.at(this->m_size) = T(std::forward<Args>(args)...);
|
||||
return this->m_data.at(this->m_size++);
|
||||
}
|
||||
constexpr void clear() { this->m_size = 0; }
|
||||
|
||||
// Accessing elements
|
||||
constexpr T& operator[](size_t idx) { return this->m_data.at(idx); }
|
||||
constexpr const T& operator[](size_t idx) const { return this->m_data.at(idx); }
|
||||
[[nodiscard]] constexpr T& at(size_t idx) {
|
||||
if (idx >= this->m_size) throw std::out_of_range("Index out of range");
|
||||
return this->m_data.at(idx);
|
||||
}
|
||||
[[nodiscard]] constexpr const T& at(size_t idx) const {
|
||||
if (idx >= this->m_size) throw std::out_of_range("Index out of range");
|
||||
return this->m_data.at(idx);
|
||||
}
|
||||
[[nodiscard]] constexpr T& front() { return this->m_data.front(); }
|
||||
[[nodiscard]] constexpr const T& front() const { return this->m_data.front(); }
|
||||
[[nodiscard]] constexpr T& back() { return this->m_data.at(this->m_size - 1); }
|
||||
[[nodiscard]] constexpr const T& back() const { return this->m_data.at(this->m_size - 1); }
|
||||
|
||||
// Iterating elements
|
||||
[[nodiscard]] constexpr T* begin() { return this->m_data.data(); }
|
||||
[[nodiscard]] constexpr const T* begin() const { return this->m_data.data(); }
|
||||
[[nodiscard]] constexpr const T* cbegin() const { return this->m_data.data(); }
|
||||
[[nodiscard]] constexpr T* end() { return this->m_data.data() + this->m_size; } // NOLINT (pointer arithmetic)
|
||||
[[nodiscard]] constexpr const T* end() const { return this->m_data.data() + this->m_size; } // NOLINT (pointer arithmetic)
|
||||
[[nodiscard]] constexpr const T* cend() const { return this->m_data.data() + this->m_size; } // NOLINT (pointer arithmetic)
|
||||
|
||||
// Removing elements
|
||||
constexpr void pop_back() {
|
||||
if (this->m_size == 0) throw std::out_of_range("Vector is empty");
|
||||
this->m_size--;
|
||||
}
|
||||
|
||||
// Query capacity
|
||||
[[nodiscard]] constexpr size_t size() const { return this->m_size; }
|
||||
[[nodiscard]] constexpr size_t capacity() const { return N; }
|
||||
[[nodiscard]] constexpr bool empty() const { return this->m_size == 0; }
|
||||
private:
|
||||
std::array<T, N> m_data{};
|
||||
size_t m_size{0};
|
||||
#pragma clang diagnostic pop
|
||||
};
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue