C スタイルの配列が壊れているためです。特に、C スタイルの配列型の関数引数を持つことはできません。関数を書く場合 (テンプレートのことは今のところ忘れます):
void foo( int arg[100] );
この言語では、コンパイラがこれを次のように処理する必要があります。
void foo( int* arg );
(そして、100
は単なるコメントであり、コンパイラによって無視されます)。
テンプレートの場合にこれをサポートするために、コンパイラが非参照テンプレート引数と一致させようとすると、配列引数がポインターに変換され、型推定は配列型ではなくポインター型になります。
main
その結果、C スタイルの配列を期待する関数 (テンプレートまたはその他) を記述してはいけません (選択肢のないの 2 番目の引数を除きます)。
この破損は C との互換性のためにのみ存在するため、参照が含まれる場合、C++ はこれに従いません。そう:
template < typename T, size_t N >
void foo( T (&arg)[ N ] );
どちらの場合でも同じ結果が得られるはずです。関数が C スタイルの配列と他のもの (std::vector など) の両方で呼び出される可能性があると思われる場合は、両方に対してオーバーロードできます。上記のバージョンはより特化されており、可能であればより一般的なバージョンよりも優先されます。
より良い解決策は、C スタイルの配列を完全に避けることですが、初期化を伴う静的変数には便利です。コンパイラに要素数をカウントさせ、初期化子リストに従って配列のサイズを定義させることができるのは、C スタイルの配列のみです。そして、静的初期化を行います。std::vector
実行時に初期化子をカウントしますが、静的変数として使用すると、初期化の順序の問題が発生する可能性があります。C スタイルの配列と