Files
Navmesher/Navmesher/utility.hpp

81 lines
2.5 KiB
C++

#pragma once
#include <array>
#include <optional>
#include <bit>
namespace utility {
// This is a base class for a generic store for some value that can be represented by
// type T but should not be type checked as type T, but rather some more constrained class.
template <class T>
struct Store {
static_assert(std::is_trivial_v<T>);
T value;
friend constexpr auto operator<=>(const Store &, const Store &) noexcept = default;
};
// Convert a fourcc literal (e.g. "LITR" to a uint32_t)
constexpr uint32_t fourcc_lit_to_val(const char(&a)[5]) noexcept
{
char temp[4] = { a[0], a[1], a[2], a[3] };
return std::bit_cast<uint32_t, char[4]>(temp);
}
// Convert a builtin array to a std::array
template <typename T, std::size_t N>
constexpr std::array<T, N> array_builtin_to_std(const T(&builtin)[N]) noexcept
{
std::array<T, N> array;
std::copy(std::cbegin(builtin), std::cend(builtin), array.begin());
return array;
}
template <typename First, typename Second, std::size_t N>
constexpr std::pair<std::array<First, N>, std::array<Second, N>> map_to_soa(std::array<std::pair<First, Second>, N> map) noexcept
{
std::array<First, N> first;
std::array<Second, N> second;
for (std::size_t i = 0; i != N; ++i) {
first[i] = map[i].first;
second[i] = map[i].second;
}
return std::make_pair(first, second);
}
template <typename First, typename Second, std::size_t N>
constexpr std::optional<Second> soa_first_to_second(const std::pair<std::array<First, N>, std::array<Second, N>> &soa, const First &first) noexcept
{
auto lhs = std::find(soa.first.cbegin(), soa.first.cend(), first);
if (lhs == soa.first.cend())
return {};
auto index = std::distance(soa.first.cbegin(), lhs);
return { soa.second[index] };
}
template <typename First, typename Second, std::size_t N>
constexpr std::optional<First> soa_second_to_first(const std::pair<std::array<First, N>, std::array<Second, N>> &soa, const Second &second) noexcept
{
auto lhs = std::find(soa.second.cbegin(), soa.second.cend(), second);
if (lhs == soa.second.cend())
return {};
auto index = std::distance(soa.second.cbegin(), lhs);
return { soa.first[index] };
}
// Used to inspect type sizes and values at compile time. Example:
//
// TS<sizeof(Type)> x = 0;
//
// or
//
// TD<Type> x = 0;
template<size_t X>
class TS;
template<typename T>
class TD;
}