1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

std::vectorとstd::arrayのネストによる多次元配列

Posted at

はじめに

C++で多次元配列を実装する場合、C言語スタイルの配列,例えば

int array[3][4][2];

をそのまま使用することも可能です.しかし,この方法ではサイズが固定されており変更ができない上に,代入操作ができないため,扱いが煩雑になることがあります.一方,以下のようにstd::vectorstd::arrayをネストして使用する方法もあります.

std::vector<std::vector<std::vector<int>>> array(3, std::vector<std::vector<int>>(4, std::vector<int>(2)));

多少のメモリオーバーヘッドやアクセスのオーバーヘッドは発生しますが,コピー代入やムーブ代入が可能であり,これらにより操作が容易になり,プログラムの見通しも良くなることが期待できます.ただし,このように宣言記述が複雑になるため,簡潔に定義するためのソースコードを備忘録としてまとめておきます.

ソースコード

std::vectorのネスト

次元(ネストの深さ)はコンパイル時に固定ですが,各次元の大きさは実行時に決定することができます.つまり,ソースコード中の次元3,4,2は定数でなく変数として実行時に指定することができます.

#include <iostream>
#include <vector>

// ベースケース: 0次元、単一のT型変数を返す
template <typename T> T nested_vector() { return T(); }

// 再帰ケース: 1次元以上、std::vectorをネストして返す
template <typename T, typename... Dims>
auto nested_vector(size_t first, Dims... dims) {
  return std::vector<decltype(nested_vector<T>(dims...))>(
      first, nested_vector<T>(dims...));
}

int main() {
  // 3x4x2のint型3次元配列を作成
  auto array = nested_vector<int>(3, 4, 2);

  // 値の代入
  array[0][0][0] = 1;
  array[2][3][1] = 42;

  // 値の確認
  std::cout << "array[0][0][0] = " << array[0][0][0] << std::endl; // 1
  std::cout << "array[2][3][1] = " << array[2][3][1] << std::endl; // 42

  return 0;
}

std::arrayのネスト

次元(ネストの深さ)と各次元の大きさはコンパイル時に固定です.

#include <array>
#include <iostream>

// ベースケース: 0次元、単一のT型変数を返す
template <typename T> T nested_array() { return T(); }

// 再帰ケース: 1次元以上、std::arrayをネストして返す
template <typename T, size_t first, size_t... Dims> auto nested_array() {
  return std::array<decltype(nested_array<T, Dims...>()), first>{};
}

int main() {
  // 3x4x2のint型3次元配列を作成
  auto array = nested_array<int, 3, 4, 2>();

  // 値の代入
  array[0][0][0] = 1;
  array[2][3][1] = 42;

  // 値の確認
  std::cout << "array[0][0][0] = " << array[0][0][0] << std::endl; // 1
  std::cout << "array[2][3][1] = " << array[2][3][1] << std::endl; // 42

  return 0;
}

おわりに

boost::multi_arrayを使って,次のように書くこともできます.

boost::multi_array<int, 3> array(boost::extents[3][4][2]);

std::vectorのネストと同様,次元は固定ですが各次元の大きさは実行時に決定することができます.

では、次元自体を実行時に決定することは可能でしょうか?結論としては,C++はPythonのような動的型付けをサポートしていないので,次元によって型が変わるこれらの方法を用いた延長線上では実現できません.

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?