From d2c14b8de4f453b49b70d6b6591223b31d7084fd Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 28 Feb 2026 18:53:50 +0000 Subject: Refactor glArrays to better expose underlying types Current they're all glNamed, but this can be sub-classed for specific things, e.g. glTexture. --- lib/glArrays.cpp | 7 --- lib/glArrays.h | 154 ++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 96 insertions(+), 65 deletions(-) (limited to 'lib') diff --git a/lib/glArrays.cpp b/lib/glArrays.cpp index 7c5b2ea..cb12f91 100644 --- a/lib/glArrays.cpp +++ b/lib/glArrays.cpp @@ -1,13 +1,6 @@ #include "glArrays.h" #include -// Base -static_assert(!std::is_default_constructible_v>); -static_assert(!std::is_copy_constructible_v>); -static_assert(!std::is_copy_assignable_v>); -static_assert(std::is_nothrow_move_constructible_v>); -static_assert(std::is_nothrow_move_assignable_v>); - // Specialisations (glBuffer is an example of the typedef) static_assert(std::is_nothrow_default_constructible_v); static_assert(!std::is_trivially_default_constructible_v); diff --git a/lib/glArrays.h b/lib/glArrays.h index 842a593..3327d8a 100644 --- a/lib/glArrays.h +++ b/lib/glArrays.h @@ -5,91 +5,129 @@ #include #include #include +#include +namespace Detail { + // NOLINTNEXTLINE(readability-identifier-naming) + class glNamed; + + template + concept IsglNamed = sizeof(Named) == sizeof(GLuint) && std::is_base_of_v; +} + +template // NOLINTNEXTLINE(readability-identifier-naming) -template class glArraysBase { - static_assert(N > 0); +struct glManagedArray; + +namespace Detail { + // NOLINTNEXTLINE(readability-identifier-naming) + class glNamed { + public: + glNamed() = default; + ~glNamed() = default; + DEFAULT_MOVE_NO_COPY(glNamed); + + GLuint + operator*() const noexcept + { + return name; + } + + // NOLINTNEXTLINE(hicpp-explicit-conversions) + operator GLuint() const noexcept + { + return name; + } -public: - ~glArraysBase() = default; - NO_COPY(glArraysBase); - CUSTOM_MOVE(glArraysBase); + protected: + GLuint name {}; + template friend struct ::glManagedArray; + }; +} - // NOLINTNEXTLINE(hicpp-explicit-conversions) - operator GLuint() const - requires(N == 1) +// NOLINTNEXTLINE(readability-identifier-naming) +template struct glManagedSingle : public Named { + glManagedSingle() noexcept { - return ids.front(); + (*Gen)(1, &this->name); } - GLuint - operator*() const - requires(N == 1) + glManagedSingle(glManagedSingle && src) noexcept { - return ids.front(); + this->name = std::exchange(src.name, 0); } - const auto & - operator[](size_t n) const + ~glManagedSingle() noexcept { - return ids[n]; + if (this->name) { + (*Del)(1, &this->name); + } } - constexpr static auto - size() + NO_COPY(glManagedSingle); + + glManagedSingle & + operator=(glManagedSingle && src) noexcept { - return N; + if (this->name) { + (*Del)(1, &this->name); + } + this->name = std::exchange(src.name, 0); + return *this; } - -protected: - glArraysBase() noexcept = default; - std::array ids {}; }; -template inline glArraysBase::glArraysBase(glArraysBase && src) noexcept : ids {src.ids} -{ - std::fill(src.ids.begin(), src.ids.end(), 0); -} - -template -inline glArraysBase & -glArraysBase::operator=(glArraysBase && src) noexcept -{ - ids = src.ids; - std::fill(src.ids.begin(), src.ids.end(), 0); - return *this; -} - +template // NOLINTNEXTLINE(readability-identifier-naming) -template class glArrays : public glArraysBase { -public: - using glArraysBase::glArraysBase; - using glArraysBase::operator=; +struct glManagedArray : public std::array { + using Arr = std::array; - DEFAULT_MOVE_COPY(glArrays); + glManagedArray() noexcept + { + (*Gen)(N, &Arr::front().name); + } + + glManagedArray(glManagedArray && src) noexcept + { + Arr::operator=(std::exchange(static_cast(src), {})); + } - glArrays() noexcept + ~glManagedArray() noexcept { - (*Gen)(N, this->ids.data()); + if (Arr::front().name) { + (*Del)(N, &Arr::front().name); + } } - ~glArrays() noexcept + NO_COPY(glManagedArray); + + glManagedArray & + operator=(glManagedArray && src) noexcept { - if (this->ids.front()) { - (*Del)(N, this->ids.data()); + if (Arr::front().name) { + (*Del)(N, &Arr::front().name); } + Arr::operator=(std::exchange(static_cast(src), {})); + return *this; + } + + [[nodiscard]] static constexpr size_t + size() noexcept + { + return N; } }; // NOLINTBEGIN(readability-identifier-naming) -template using glVertexArrays = glArrays; -using glVertexArray = glVertexArrays<1>; -template using glBuffers = glArrays; -using glBuffer = glBuffers<1>; -template using glTextures = glArrays; -using glTexture = glTextures<1>; -template using glFrameBuffers = glArrays; -using glFrameBuffer = glFrameBuffers<1>; -template using glRenderBuffers = glArrays; -using glRenderBuffer = glRenderBuffers<1>; +template using glVertexArrays = glManagedArray; +using glVertexArray = glManagedSingle; +template using glBuffers = glManagedArray; +using glBuffer = glManagedSingle; +template using glTextures = glManagedArray; +using glTexture = glManagedSingle; +template using glFrameBuffers = glManagedArray; +using glFrameBuffer = glManagedSingle; +template +using glRenderBuffers = glManagedArray; +using glRenderBuffer = glManagedSingle; // NOLINTEND(readability-identifier-naming) -- cgit v1.3