summaryrefslogtreecommitdiffhomepage
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/array-size.hpp8
-rw-r--r--compat/assert.cpp38
-rw-r--r--compat/assert.hpp61
-rw-r--r--compat/borrowed-ptr-fwd.hpp8
-rw-r--r--compat/borrowed-ptr.cpp2
-rw-r--r--compat/borrowed-ptr.hpp8
-rw-r--r--compat/borrowed-ptr.inl23
-rw-r--r--compat/format.hpp10
-rw-r--r--compat/fpu.hpp4
-rw-r--r--compat/function2.hpp4
-rw-r--r--compat/heap.hpp48
-rw-r--r--compat/intrusive-ptr.hpp8
-rw-r--r--compat/unroll.hpp13
13 files changed, 163 insertions, 72 deletions
diff --git a/compat/array-size.hpp b/compat/array-size.hpp
index 15eb66ab..98da4d1e 100644
--- a/compat/array-size.hpp
+++ b/compat/array-size.hpp
@@ -5,15 +5,19 @@ namespace floormat::detail {
template<typename T> struct array_size_;
template<typename T, size_t N> struct array_size_<T(&)[N]> : std::integral_constant<size_t, N> {};
+template<typename T, size_t N> struct array_size_<T(*)[N]> : std::integral_constant<size_t, N> {};
template<typename T, size_t N> struct array_size_<T[N]> : std::integral_constant<size_t, N> {};
template<typename T, size_t N> struct array_size_<std::array<T, N>> : std::integral_constant<size_t, N> {};
template<typename T, size_t N> struct array_size_<StaticArray<N, T>> : std::integral_constant<size_t, N> {};
+template<typename C, typename T> struct array_size_<T C::*> : std::integral_constant<size_t, array_size_<std::remove_cvref_t<T>>::value> {};
+//template<typename T, typename U, size_t N> struct array_size_< T(U::*)[N] > : std::integral_constant<size_t, N> {}; // should be redundant
+
} // namespace floormat::detail
namespace floormat {
-template<typename T> constexpr inline size_t static_array_size = detail::array_size_<T>::value;
-template<typename T> constexpr inline size_t array_size(const T&) noexcept { return detail::array_size_<T>::value; }
+template<typename T> constexpr inline size_t static_array_size = detail::array_size_<std::remove_cvref_t<T>>::value;
+template<typename T> constexpr inline size_t array_size(const T&) noexcept { return detail::array_size_<std::remove_cvref_t<T>>::value; }
} // namespace floormat
diff --git a/compat/assert.cpp b/compat/assert.cpp
index cd6e9af3..3f030b6b 100644
--- a/compat/assert.cpp
+++ b/compat/assert.cpp
@@ -1,4 +1,5 @@
#include "assert.hpp"
+#include "exception.hpp"
#include <cstdlib>
#include <cstdio>
#include <cstdarg>
@@ -7,13 +8,15 @@
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
-namespace floormat {
+namespace floormat::debug::detail {
namespace {
+bool do_soft_assert = false;
+
template<bool DoPrefix, bool DoSourceLocation>
CORRADE_NEVER_INLINE
-void fm_emit_debug_(const char* prefix, const char* file, int line, const char* fmt, va_list arg_ptr)
+void emit_debug_(const char* prefix, const char* file, int line, const char* fmt, va_list arg_ptr)
{
std::fflush(stdout);
std::fflush(stderr);
@@ -29,31 +32,31 @@ void fm_emit_debug_(const char* prefix, const char* file, int line, const char*
} // namespace
-void fm_emit_debug(const char* prefix, fm_FORMAT_ARG_MSVC const char* fmt, ...)
+void emit_debug(const char* prefix, fm_FORMAT_ARG_MSVC const char* fmt, ...)
{
va_list arg_ptr;
va_start(arg_ptr, fmt);
- fm_emit_debug_<true, false>(prefix, nullptr, 0, fmt, arg_ptr);
+ emit_debug_<true, false>(prefix, nullptr, 0, fmt, arg_ptr);
va_end(arg_ptr);
}
-void fm_emit_debug0(fm_FORMAT_ARG_MSVC const char* fmt, ...)
+void emit_debug0(fm_FORMAT_ARG_MSVC const char* fmt, ...)
{
va_list arg_ptr;
va_start(arg_ptr, fmt);
- fm_emit_debug_<false, false>(nullptr, nullptr, 0, fmt, arg_ptr);
+ emit_debug_<false, false>(nullptr, nullptr, 0, fmt, arg_ptr);
va_end(arg_ptr);
}
-void CORRADE_NEVER_INLINE fm_emit_debug_loc(const char* prefix, const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...)
+void CORRADE_NEVER_INLINE emit_debug_loc(const char* prefix, const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...)
{
va_list arg_ptr;
va_start(arg_ptr, fmt);
- fm_emit_debug_<true, true>(prefix, file, line, fmt, arg_ptr);
+ emit_debug_<true, true>(prefix, file, line, fmt, arg_ptr);
va_end(arg_ptr);
}
-void fm_emit_assert_fail(const char* expr, const char* file, int line)
+void emit_assert_fail(const char* expr, const char* file, int line)
{
std::fflush(stdout);
std::fflush(stderr);
@@ -62,20 +65,29 @@ void fm_emit_assert_fail(const char* expr, const char* file, int line)
std::abort();
}
-void fm_emit_abort(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...)
+void emit_abort(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...)
{
va_list arg_ptr;
va_start(arg_ptr, fmt);
- fm_emit_debug_<true, true>("fatal: ", file, line, fmt, arg_ptr);
+ emit_debug_<true, true>("fatal: ", file, line, fmt, arg_ptr);
va_end(arg_ptr);
std::abort();
}
-void fm_emit_abort()
+void emit_abort()
{
std::fflush(stdout);
std::fflush(stderr);
std::abort();
}
-} // namespace floormat
+} // namespace floormat::debug::detail
+
+using namespace floormat::debug::detail;
+
+namespace floormat::debug {
+
+void set_soft_assert_mode(bool value) { do_soft_assert = value; }
+bool soft_assert_mode() { return detail::do_soft_assert; }
+
+} // namespace floormat::debug
diff --git a/compat/assert.hpp b/compat/assert.hpp
index 8c882b0e..1333c6a6 100644
--- a/compat/assert.hpp
+++ b/compat/assert.hpp
@@ -12,16 +12,29 @@
#define fm_FORMAT_ARG_MSVC
#endif
-namespace floormat {
+namespace floormat::debug::detail {
+
+void emit_debug(const char* prefix, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(2);
+void emit_debug0(fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(1);
+void emit_debug_loc(const char* prefix, const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(4);
+void emit_debug_loc0(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(3);
+
+[[noreturn]] CORRADE_NEVER_INLINE void emit_assert_fail(const char* expr, const char* file, int line);
+[[noreturn]] CORRADE_NEVER_INLINE void emit_abort(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(3);
+[[noreturn]] CORRADE_NEVER_INLINE void emit_abort();
+
+} // namespace floormat::debug::detail
+
+
+namespace floormat::debug {
+
+void set_soft_assert_mode(bool value);
+bool soft_assert_mode();
-void fm_emit_debug(const char* prefix, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(2);
-void fm_emit_debug0(fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(1);
-void fm_emit_debug_loc(const char* prefix, const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(4);
-void fm_emit_debug_loc0(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(3);
+} // namespace floormat::debug
-[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_assert_fail(const char* expr, const char* file, int line);
-[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_abort(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(3);
-[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_abort();
+
+namespace floormat {
} // namespace floormat
@@ -30,19 +43,29 @@ void fm_emit_debug_loc0(const char* file, int line, fm_FORMAT_ARG_MSVC const cha
#pragma GCC diagnostic ignored "-Wunused-macros"
#endif
-#define fm_assert(...) ((__VA_ARGS__) ? void() : ::floormat::fm_emit_assert_fail(#__VA_ARGS__, __FILE__, __LINE__))
-#define fm_abort(...) (::floormat::fm_emit_abort(__FILE__, __LINE__, __VA_ARGS__))
-#define fm_warn(...) (::floormat::fm_emit_debug("warning: ", __VA_ARGS__))
-#define fm_error(...) (::floormat::fm_emit_debug("error: ", __VA_ARGS__))
-#define fm_log(...) (::floormat::fm_emit_debug0(__VA_ARGS__))
-#define fm_debug(...) (::floormat::fm_emit_debug0(__VA_ARGS__))
-#define fm_debug_loc(pfx, ...) (::floormat::fm_emit_debug_loc(pfx, __FILE__, __LINE__,__VA_ARGS__))
-#define fm_debug_loc0(...) (::floormat::fm_emit_debug_loc0(__FILE__, __LINE__,__VA_ARGS__))
+#define fm_assert(...) ((__VA_ARGS__) ? void() : ::floormat::debug::detail::emit_assert_fail(#__VA_ARGS__, __FILE__, __LINE__))
+#define fm_abort(...) (::floormat::debug::detail::emit_abort(__FILE__, __LINE__, __VA_ARGS__))
+#define fm_warn(...) (::floormat::debug::detail::emit_debug("warning: ", __VA_ARGS__))
+#define fm_error(...) (::floormat::debug::detail::emit_debug("error: ", __VA_ARGS__))
+#define fm_log(...) (::floormat::debug::detail::emit_debug0(__VA_ARGS__))
+#define fm_debug(...) (::floormat::debug::detail::emit_debug0(__VA_ARGS__))
+#define fm_debug_loc(pfx, ...) (::floormat::debug::detail::emit_debug_loc(pfx, __FILE__, __LINE__,__VA_ARGS__))
+#define fm_debug_loc0(...) (::floormat::debug::detail::emit_debug_loc0(__FILE__, __LINE__,__VA_ARGS__))
+
+#if defined FM_NO_DEBUG && !defined FM_NO_DEBUG2
+#define FM_NO_DEBUG2
+#endif
#ifndef FM_NO_DEBUG
#define fm_debug_assert(...) fm_assert(__VA_ARGS__)
#else
-#define fm_debug_assert(...) void()
+#define fm_debug_assert(...) (void())
+#endif
+
+#ifndef FM_NO_DEBUG2
+#define fm_debug2_assert(...) fm_assert(__VA_ARGS__)
+#else
+#define fm_debug2_assert(...) (void())
#endif
#define fm_warn_once(...) do { \
@@ -66,7 +89,7 @@ void fm_emit_debug_loc0(const char* file, int line, fm_FORMAT_ARG_MSVC const cha
ERR_nospace << #__VA_ARGS__; \
ERR_nospace << " expected: " << a; \
ERR_nospace << " actual: " << b; \
- fm_emit_abort(); \
+ ::floormat::debug::detail::emit_abort(); \
} \
})(__VA_ARGS__)
@@ -83,7 +106,7 @@ void fm_emit_debug_loc0(const char* file, int line, fm_FORMAT_ARG_MSVC const cha
ERR_nospace << #__VA_ARGS__; \
ERR_nospace << "not expected: " << a; \
ERR_nospace << " actual: " << b; \
- fm_emit_abort(); \
+ ::floormat::debug::detail::emit_abort(); \
} \
})(__VA_ARGS__)
diff --git a/compat/borrowed-ptr-fwd.hpp b/compat/borrowed-ptr-fwd.hpp
index 8fcc5dde..48c3e141 100644
--- a/compat/borrowed-ptr-fwd.hpp
+++ b/compat/borrowed-ptr-fwd.hpp
@@ -2,12 +2,18 @@
namespace floormat {
+#define FM_BPTR_DEBUG
+//#define FM_NO_WEAK_BPTR
+
struct bptr_base;
template<typename T> class bptr;
template<typename T> class weak_bptr;
template<typename T> bptr(T* ptr) -> bptr<T>;
-template<typename T> bptr(const T* ptr) -> bptr<const T>;
+
+#ifndef FM_NO_WEAK_BPTR
+template<typename T> weak_bptr(const bptr<T>& ptr) -> weak_bptr<T>;
+#endif
} // namespace floormat
diff --git a/compat/borrowed-ptr.cpp b/compat/borrowed-ptr.cpp
index 1dded12a..e64468d5 100644
--- a/compat/borrowed-ptr.cpp
+++ b/compat/borrowed-ptr.cpp
@@ -4,6 +4,8 @@ namespace floormat::detail_bptr {
void control_block::decrement(control_block*& blk) noexcept
{
+ if (!blk)
+ return;
auto c2 = --blk->_hard_count;
fm_bptr_assert(c2 != (uint32_t)-1);
if (c2 == 0)
diff --git a/compat/borrowed-ptr.hpp b/compat/borrowed-ptr.hpp
index 6a4e79f1..b818154c 100644
--- a/compat/borrowed-ptr.hpp
+++ b/compat/borrowed-ptr.hpp
@@ -1,9 +1,5 @@
#pragma once
#include "borrowed-ptr-fwd.hpp"
-#include <compare>
-
-#define FM_BPTR_DEBUG
-#define FM_NO_WEAK_BPTR
#ifdef __CLION_IDE__
#define fm_bptr_assert(...) (void(__VA_ARGS__))
@@ -113,10 +109,6 @@ public:
bool operator==(const bptr<T>& other) const noexcept requires (!std::is_const_v<T>);
bool operator==(const std::nullptr_t& other) const noexcept;
- std::strong_ordering operator<=>(const bptr<const T>& other) const noexcept;
- std::strong_ordering operator<=>(const bptr<T>& other) const noexcept requires (!std::is_const_v<T>);
- std::strong_ordering operator<=>(const std::nullptr_t&) const noexcept;
-
template<typename U> friend class bptr;
template<typename U> friend class weak_bptr;
diff --git a/compat/borrowed-ptr.inl b/compat/borrowed-ptr.inl
index e1a5f591..d8c561a5 100644
--- a/compat/borrowed-ptr.inl
+++ b/compat/borrowed-ptr.inl
@@ -9,7 +9,7 @@
namespace floormat {
-template<typename T> bptr<T>::~bptr() noexcept { if (blk) detail_bptr::control_block::decrement(blk); }
+template<typename T> bptr<T>::~bptr() noexcept { detail_bptr::control_block::decrement(blk); }
template<typename T> bptr<T>::bptr(const bptr<std::remove_const_t<T>>& ptr) noexcept requires std::is_const_v<T>: bptr{ptr, nullptr} {}
template<typename T> bptr<T>::bptr(bptr<std::remove_const_t<T>>&& ptr) noexcept requires std::is_const_v<T>: bptr{move(ptr), nullptr} {}
@@ -41,14 +41,13 @@ template<detail_bptr::DerivedFrom<T> Y>
bptr<T>& bptr<T>::operator=(bptr<Y>&& other) noexcept
{ return _move_assign(move(other)); }
-template<typename T> void bptr<T>::reset() noexcept { if (blk) detail_bptr::control_block::decrement(blk); }
+template<typename T> void bptr<T>::reset() noexcept { detail_bptr::control_block::decrement(blk); }
template<typename T>
template<detail_bptr::DerivedFrom<T> Y>
void bptr<T>::reset(Y* ptr) noexcept
{
- if (blk)
- detail_bptr::control_block::decrement(blk);
+ detail_bptr::control_block::decrement(blk);
blk = ptr ? new detail_bptr::control_block{const_cast<std::remove_const_t<Y>*>(ptr), 1,
#ifndef FM_NO_WEAK_BPTR
1,
@@ -95,8 +94,7 @@ bptr<T>& bptr<T>::_copy_assign(const bptr<Y>& other) noexcept
{
if (blk != other.blk)
{
- if (blk)
- detail_bptr::control_block::decrement(blk);
+ detail_bptr::control_block::decrement(blk);
blk = other.blk;
if (blk)
{
@@ -113,8 +111,7 @@ template<typename T>
template<typename Y>
bptr<T>& bptr<T>::_move_assign(bptr<Y>&& other) noexcept
{
- if (blk)
- detail_bptr::control_block::decrement(blk);
+ detail_bptr::control_block::decrement(blk);
blk = other.blk;
other.blk = nullptr;
return *this;
@@ -151,16 +148,6 @@ template<typename T> bool bptr<T>::operator==(const bptr<T>& other) const noexce
template<typename T> bool bptr<T>::operator==(const std::nullptr_t&) const noexcept { return !blk || !blk->_ptr; }
-template<typename T>
-std::strong_ordering bptr<T>::operator<=>(const bptr<const T>& other) const noexcept
-{ return get() <=> other.get(); }
-
-template<typename T> std::strong_ordering bptr<T>::operator<=>(const bptr<T>& other) const noexcept requires (!std::is_const_v<T>)
-{ return get() <=> other.get(); }
-
-template<typename T> std::strong_ordering bptr<T>::operator<=>(const std::nullptr_t&) const noexcept
-{ return get() <=> (T*)nullptr; }
-
template<typename T> void bptr<T>::swap(bptr& other) noexcept { floormat::swap(blk, other.blk); }
template<typename T>
diff --git a/compat/format.hpp b/compat/format.hpp
index 1cb4f365..800bce5a 100644
--- a/compat/format.hpp
+++ b/compat/format.hpp
@@ -9,12 +9,12 @@ namespace fmt {
template<> struct formatter<Corrade::Containers::StringView> {
template<typename ParseContext> static constexpr auto parse(ParseContext& ctx) { return ctx.begin(); }
- template<typename FormatContext> auto format(Corrade::Containers::StringView const& s, FormatContext& ctx);
+ template<typename FormatContext> auto format(Corrade::Containers::StringView const& s, FormatContext& ctx) const;
};
template<> struct formatter<Corrade::Containers::String> {
template<typename ParseContext> static constexpr auto parse(ParseContext& ctx) { return ctx.begin(); }
- template<typename FormatContext> auto format(Corrade::Containers::String const& s, FormatContext& ctx);
+ template<typename FormatContext> auto format(Corrade::Containers::String const& s, FormatContext& ctx) const;
};
} // namespace fmt
@@ -42,7 +42,7 @@ consteval auto operator""_cf() noexcept
return FMT_COMPILE(s.data);
}
#else
-using namespace fmt::literals;
+using fmt::literals::operator""_cf;
#endif
namespace floormat {
@@ -66,11 +66,11 @@ size_t snformat(char(&buf)[N], Fmt&& fmt, Xs&&... args)
} // namespace floormat
template<typename FormatContext>
-auto fmt::formatter<Corrade::Containers::StringView>::format(Corrade::Containers::StringView const& s, FormatContext& ctx) {
+auto fmt::formatter<Corrade::Containers::StringView>::format(Corrade::Containers::StringView const& s, FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "{}"_cf, basic_string_view<char>{s.data(), s.size()});
}
template<typename FormatContext>
-auto fmt::formatter<Corrade::Containers::String>::format(Corrade::Containers::String const& s, FormatContext& ctx) {
+auto fmt::formatter<Corrade::Containers::String>::format(Corrade::Containers::String const& s, FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "{}"_cf, basic_string_view<char>{s.data(), s.size()});
}
diff --git a/compat/fpu.hpp b/compat/fpu.hpp
index 9433648a..e72e8fdd 100644
--- a/compat/fpu.hpp
+++ b/compat/fpu.hpp
@@ -19,7 +19,11 @@ static inline void set_fp_mask()
#endif
#ifdef __APPLE__
+#if defined __386__ || defined __x86_64__
fesetenv(FE_DFL_DISABLE_SSE_DENORMS_ENV);
+#elif defined __arm64__
+ fesetenv(FE_DFL_DISABLE_DENORMS_ENV);
+#endif
#endif
#ifdef _WIN32
diff --git a/compat/function2.hpp b/compat/function2.hpp
index 9e6b9b50..f53dcf7f 100644
--- a/compat/function2.hpp
+++ b/compat/function2.hpp
@@ -1082,8 +1082,8 @@ struct internal_capacity {
/// Tag to access the structure in a type-safe way
data_accessor accessor_;
/// The internal capacity we use to allocate in-place
- struct {
- alignas(Capacity::alignment) unsigned char data[Capacity::capacity];
+ struct alignas(Capacity::alignment) {
+ unsigned char data[Capacity::capacity];
} capacity_;
} type;
};
diff --git a/compat/heap.hpp b/compat/heap.hpp
index 3d901755..665d11e3 100644
--- a/compat/heap.hpp
+++ b/compat/heap.hpp
@@ -1,6 +1,54 @@
#pragma once
#if defined __GLIBCXX__ && defined _GLIBCXX_DEBUG
+// Heap implementation -*- C++ -*-
+
+// Copyright (C) 2001-2024 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
#include <utility>
#include <iterator>
// regular STL implementation stripped of debug code
diff --git a/compat/intrusive-ptr.hpp b/compat/intrusive-ptr.hpp
index 8e9b3d6c..c8cf6ff3 100644
--- a/compat/intrusive-ptr.hpp
+++ b/compat/intrusive-ptr.hpp
@@ -41,10 +41,10 @@ struct refcount_ops
using Tref = T*;
#endif
- static constexpr inline auto incr(T* ptr) noexcept -> size_type; // todo! remove constexpr from everywhere, then move everything to .inl
- static constexpr inline auto decr(Tref ptr) noexcept -> size_type;
- static constexpr inline auto count(T* ptr) noexcept -> size_type;
- static constexpr inline void init_to_1(T* ptr) noexcept;
+ static constexpr auto incr(T* ptr) noexcept -> size_type; // todo! remove constexpr from everywhere, then move everything to .inl
+ static constexpr auto decr(Tref ptr) noexcept -> size_type;
+ static constexpr auto count(T* ptr) noexcept -> size_type;
+ static constexpr void init_to_1(T* ptr) noexcept;
};
template<typename Tag, typename T>
diff --git a/compat/unroll.hpp b/compat/unroll.hpp
new file mode 100644
index 00000000..2b74ed1a
--- /dev/null
+++ b/compat/unroll.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+namespace floormat {
+
+template<uint32_t Max, typename F>
+constexpr CORRADE_ALWAYS_INLINE void unroll(F&& fn)
+{
+ [&]<size_t... Is>(std::index_sequence<Is...>) {
+ (..., fn(std::integral_constant<size_t, Is>{}));
+ }(std::make_index_sequence<Max>());
+}
+
+} // namespace floormat