受け入れられた答えは、文字列を使用して多次元インデックスを表すことを推奨しています。
ただし、文字列を構築することは、これには不必要に無駄です。コンパイル時にサイズがわからない (したがってstd::tuple
機能しない) 場合はstd::vector
、ハッシュ マップと順序付けられたツリーの両方で、インデックスとして適切に機能します。の場合std::map
、これはほとんど自明です。
#include <vector>
#include <map>
using index_type = std::vector<int>;
template <typename T>
using sparse_array = std::map<index_type, T>;
std::unordered_map
(または同様のハッシュテーブルベースの辞書)の場合、特殊化されていないため、少し手間がかかりstd::vector
ますstd::hash
:
#include <vector>
#include <unordered_map>
#include <numeric>
using index_type = std::vector<int>;
struct index_hash {
std::size_t operator()(index_type const& i) const noexcept {
// Like boost::hash_combine; there might be some caveats, see
// <https://stackoverflow.com/a/50978188/1968>
auto const hash_combine = [](auto seed, auto x) {
return std::hash<int>()(x) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
};
return std::accumulate(i.begin() + 1, i.end(), i[0], hash_combine);
}
};
template <typename T>
using sparse_array = std::unordered_map<index_type, T, index_hash>;
どちらの方法でも、使用方法は同じです。
int main() {
using i = index_type;
auto x = sparse_array<int>();
x[i{1, 2, 3}] = 42;
x[i{4, 3, 2}] = 23;
std::cout << x[i{1, 2, 3}] + x[i{4, 3, 2}] << '\n'; // 65
}