dimensional_array.h (3312B)
1 // Sourced from https://github.com/BreadFish64/ScaleFish/blob/master/common/dimensional_array.hpp 2 // Copyright (c) 2020 BreadFish64 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in all 12 // copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 // SOFTWARE. 21 22 #pragma once 23 24 #include <array> 25 #include <cstdint> 26 #include <type_traits> 27 28 namespace detail { 29 template<typename T, std::size_t rank, std::size_t... sizes> 30 struct DimensionalArrayExplicitRank; 31 32 // Workaround for VS2017 & VS 16.9.x 33 #if defined(_MSC_VER) && (_MSC_VER < 1920 || _MSC_VER == 1928) 34 35 template<std::size_t rank, std::size_t... sizes> 36 struct GetRankSize 37 { 38 static constexpr std::size_t size_array[] = {sizes...}; 39 static constexpr std::size_t value = size_array[rank - 1]; 40 }; 41 42 template<typename T, std::size_t rank, std::size_t... sizes> 43 using GetArrayImplType = 44 std::array<std::conditional_t<rank == 1, T, DimensionalArrayExplicitRank<T, rank - 1, sizes...>>, 45 GetRankSize<rank, sizes...>::value>; 46 47 #else 48 49 template<std::size_t rank, std::size_t... sizes> 50 constexpr std::size_t GetRankSize() 51 { 52 constexpr std::size_t size_array[] = {sizes...}; 53 return size_array[rank - 1]; 54 } 55 56 template<typename T, std::size_t rank, std::size_t... sizes> 57 using GetArrayImplType = 58 std::array<std::conditional_t<rank == 1, T, DimensionalArrayExplicitRank<T, rank - 1, sizes...>>, 59 GetRankSize<rank, sizes...>()>; 60 61 #endif 62 63 template<typename T, std::size_t rank_param, std::size_t... sizes> 64 struct DimensionalArrayExplicitRank : public GetArrayImplType<T, rank_param, sizes...> 65 { 66 static constexpr std::size_t rank = rank_param; 67 static_assert(rank > 0, "Attempted to create dimensional array with rank less than 1"); 68 using ArrayImplType = GetArrayImplType<T, rank, sizes...>; 69 using ArrayImplType::ArrayImplType; 70 71 template<typename Callable> 72 void enumerate(const Callable& f) 73 { 74 for (auto& it : *this) 75 { 76 if constexpr (rank == 1) 77 f(it); 78 else 79 it.enumerate(f); 80 } 81 } 82 83 template<typename Callable> 84 void enumerate(const Callable& f) const 85 { 86 for (const auto& it : *this) 87 { 88 if constexpr (rank == 1) 89 f(it); 90 else 91 it.enumerate(f); 92 } 93 } 94 }; 95 } // namespace detail 96 97 template<typename T, std::size_t... sizes> 98 using DimensionalArray = detail::DimensionalArrayExplicitRank<T, sizeof...(sizes), sizes...>;