質問: ### 前提・実現したいこと 関数を利用して動的に宣言したグローバル変数(?)を配列の要素数として配列を宣言し、関数に渡したい。 ### 発生している問題・エラーメッセージ 二次元以上の配列だとうまく機能していないことが明らかになる。 > > No matching function for call to 'test2' > > No matching function for call to 'test4' > > > これをコンパイルしようとしてみると > > Candidate function not viable:no known conversion from 'char[Num][Num]'to 'char(*)[Num]'for 1st argument > > Candidate function not viable:no known conversion from 'char[dNum][dNum]'to 'char(*)[dNum]'for 1st argument > > > このようなエラーを吐きます。 ### ソースコード ``` #include using namespace std; const int N=7; int fact(int n) { int all_hs=1; for(int i=1;i<=n;i++){ all_hs=all_hs*i; } return all_hs; } const int Num=fact(N-3);//4*3*2*1=24; #define dNum fact(N-3)//4*3*2*1=24; void test1(char t[Num]){} void test2(char t[][Num]){} void test3(char t[24][24]){} void test4(char t[dNum][dNum]){} int main() { char t_1[Num]; char t_2[Num][Num]; char t_3[24][24]; char t_4[dNum][dNum]; test1(t_1); test2(t_2);//No matching function for call to 'test2' test3(t_3); test4(t_4);//No matching function for call to 'test4' } ``` ### 補足情報(言語/FW/ツール等のバージョンなど) コンパイラ(?)厳密には違うらしいんですが・・・ XcodeにプリインストールされていたGCCの一種だと思うのですがApple LLVM7.0です。 なんとなく計算されるタイミングとかが関係あるのかなと思うんですが、理解が甘く良くわかっておりません。 正確な理解と、具体的な解決策が見つかったらと思っています。
回答: こんにちは。 関数fact()は通常の関数ですので、Num、および、dNumは実行時にしか決まりません。 しかし、C++は配列の要素数はコンパイル時にきまっている必要が有ります。 ですので、コンパイルエラーがでます。 さて、C++11規格でこのような時にたいへんありがたいconstexprが追加され、C++14で使える範囲が広がっています。これを関数につけると、コンパイル時に計算してくれるのです。 もちろん、引数等全ての必要データがコンパイル時に決まっている必要がありますが、今回の引数N-3はコンパイル時に決まっているので、C++14であればconstexprをつけるだけでビルドできます。 ``` constexpr int fact(int n) ``` 取り敢えずfact()関数にconstexprを付けてみると良いと思います。 エラーがでるようでしたら、コンパイル・オプションに`-std=C++14`を追加すればいける可能性があります。 手元のMinGW(gcc)5.2.0ではできました。ただ、4.9.1ではだめだったので、バージョンによると思います。 LLVM/clangはgccよりC++14対応が進んでいると聞きますので、`Apple LLVM7.0`がLLVM 3.7.0に近いバージョンでしたら恐らく大丈夫です。