C++ 言語で、添え字から計算される値を要素とするN(コンパイル時定数)元配列をコンパイル時定数として定義するにはどうすれば良いですか?
例えば、添え字 i に対して、位置iの要素は、i(i+1)/2 という計算式で与えられるint型の値としたいとき、N=10に対して手計算で
C++
1constexpr int array[] = {0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55};
と書くのは煩わしいので、右辺を添え字から計算式で表したいのですが、それはどのようにしたらできますか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/19 09:34
回答2件
0
ベストアンサー
もしも C++20 を前提に出来るなら constexpr
に関する要件はかなり緩められているので難しいことは何もありません。 配列に代入して返すだけです。
cpp
1#include <iostream> 2#include <array> 3 4template<std::size_t N> 5constexpr std::array<int, N> make_array(void) { 6 std::array<int, N> r; 7 for(std::size_t i=0; i<N; i++) r[i] = i*(i+1)/2; 8 return r; 9} 10 11int main(void) { 12 constexpr auto array = make_array<10>(); 13 for(int a: array) std::cout << a << std::endl; 14}
C++11 だと仮定すると SFINAE を活用したメタプログラミングが必要になります。
cpp
1#include <iostream> 2#include <array> 3 4template<int N> 5class array_builder { 6 template<int M, int i> 7 struct helper { 8 template<class... T> 9 constexpr static std::array<int, N> invoke(T... args) { 10 return helper<N, i+1>::invoke(args..., i*(i+1)/2); 11 } 12 }; 13 14 template<int M> 15 struct helper<M, M> { 16 template<class... T> 17 constexpr static std::array<int, N> invoke(T... args) { 18 return std::array<int, N>{args...}; 19 } 20 }; 21 22public: 23 constexpr static std::array<int, N> value = helper<N, 0>::invoke(); 24}; 25 26int main(void) { 27 constexpr auto array = array_builder<10>::value; 28 for(int a: array) std::cout << a << std::endl; 29}
難解な仕組みなので必要な知識を全てここで説明することはできません。 SFINAE をキーワードにして資料を探してみてください。
その上で不明なことがあるようならあらためて個別の質問をしてください。
投稿2020/06/19 06:38
総合スコア5684
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/19 09:36 編集
2020/06/20 04:58
2020/06/22 01:39
0
マクロを使うことにします。
2 のべき乗なら簡単。そうでない場合は、2のべき乗の和と考えます。
11 = 8 + 2 + 1 です。
C
1#include <iostream> 2 3#define T4(x) T3(x),T3(x+8) 4#define T3(x) T2(x),T2(x+4) 5#define T2(x) T1(x),T1(x+2) 6#define T1(x) T0(x),T0(x+1) 7#define T0(x) ((x)*((x)+1)/2) 8 9constexpr int array16[] = { T4(0) }; 10constexpr int array11[] = { T3(0), T1(8), T0(10) }; 11 12int main() 13{ 14 for (int e : array16) std::cout << ' ' << e; 15 std::cout < '\n'; 16 for (int e : array11) std::cout << ' ' << e; 17 std::endl(std::cout); 18}
実行結果
0 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 0 1 3 6 10 15 21 28 36 45 55
投稿2020/06/22 03:42
編集2020/06/22 03:50総合スコア8224
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。