質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

1577閲覧

C++で計算式から計算するコンパイル時定数配列

tails

総合スコア22

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

1グッド

1クリップ

投稿2020/06/19 02:42

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};

と書くのは煩わしいので、右辺を添え字から計算式で表したいのですが、それはどのようにしたらできますか。

yohhoy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ohys

2020/06/19 05:06

なぜconstexprにこだわるのか? constexprが無ければ自力でできるのですか?
tails

2020/06/19 09:34

ただなんとなく、ふと今のC++20の言語仕様的にできるのかな?と気になっただけです。 コンパイル時定数でなければできますので…
guest

回答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

SaitoAtsushi

総合スコア5684

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tails

2020/06/19 09:36 編集

ご回答ありがとうございます。 今回は、std::array ではなく、プリミティブな配列型でそれが可能な文法が存在するのかどうか、という質問でした。 SFINAE でご回答いただきありがとうございます。 気が向いたらまた調べてみたいと思います。 プリミティブな配列型 T[] では、可能でしょうか。 つまり、そのような要求を満たす仕様が、最新のC++には自分がしらないだけで実はあるのでは!?と期待してました。
SaitoAtsushi

2020/06/20 04:58

C/C++ における配列は第一級オブジェクトではありません。 これについての不満に対する解として `std::array` が導入されました。 なので、あくまでも配列でやりたいというのはおそらく無理です。 ものすごいアクロバティックなことをすれば出来る可能性はあるのかもしれませんが、少なくとも私の知識の範囲では出来ないですね。
tails

2020/06/22 01:39

なるほど、わかりました。 ありがとうございました!
guest

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
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tails

2020/06/22 13:16

これはちょっと面白いですね(笑) 実用的かどうかは分かりませんが、ネタとして知ってても面白いなと思いました! ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問