目的
例えばこんな構造体があって、メンバーの配列に値を設定したいとします。
今更変更なんて出来ないヘッダー.h
struct Hoge {
/* 省略 */
uint8_t hoge_color[4]; // RGBA
};
C++では良くあることです。
// 当然エラーになる
hoge.hoge_color = {255, 255, 255, 0};
こんなときRustであったならば…
もし、現状の開発環境がRustに対応していれば、悩む必要は無かったでしょう。
// 当然のように動く
hoge.hoge_color = [255, 255, 255, 0];
// これも行ける
let _ = std::mem::replace(&mut hoge.hoge_color, [255, 255, 255, 0]);
// サイズ不一致だとコンパイルエラー
hoge.hoge_color = [5, 4, 3, 2, 1, 0, 0, 0];
手遅れでなければ
もし、構造体の定義を変更できるのであれば、配列をstd::arrayに変更すべきです。
変更が間に合ったヘッダー.h
#include <array>
struct Hoge {
/* 省略 */
std::array<uint8_t, 4> hoge_color; // RGBA
};
// 動く
hoge.hoge_color = {255, 255, 255, 0};
std::arrayは、配列の代替として(十年以上前に)提案されたクラスです。
C++で配列からstd::arrayに移行しないのはバッドプラクティスです…と言いたいところですが、そもそもC++の存在そのものがバッドプラクティスでしょう。
しかしながら、このような解決策をとれないことも、C++では良くあることです。
解決策(暫定)
以下のように書けるよう、テンプレート関数を定義してみました。
set_array(hoge.hoge_color, {255, 255, 255, 0});
関数の中身は以下の通りです。
#include <algorithm>
#include <array>
template <typename T, size_t N>
inline void set_array(T (&dest)[N], const std::array<T, N> &src)
{
std::copy(src.begin(), src.end(), std::begin(dest));
}
第一引数がよく分からないことになっています。この様にすることで、固定長配列を引数にできるらしいです。
第二引数は先程登場したstd::arrayですね。何故かこちらを使用しないと動かなかった…。
おしまい
- C++には、昔ながらの代入出来ない配列と、代入できるstd::arrayがある
-
この状況でも入れる保険があるんですか代入出来ない配列も、テンプレートを利用することで、それっぽいことはできる - もっと良い書き方はないだろうか?