web-dev-qa-db-ja.com

C ++の可変個引数関数宣言でコンマが省略されています

私は次のような可変個引数関数を宣言することに慣れています。

_int f(int n, ...);
_

読んでいるときC++プログラミング言語本の宣言ではコンマが省略されていることがわかりました。

_int f(int n...); // the comma has been omitted
_

Cコンパイラを使用してコンパイルしようとするとこのエラーが発生するため、この構文はC++固有のようです。

test.c:1:12: error: expected ‘;’, ‘,’ or ‘)’ before ‘...’ token int f(int n...);

int f(int n, ...)と_int f(int n..._)の記述に違いはありますか?

この構文がC++で追加されたのはなぜですか?

42
wefwefa3

C++標準の§8.3.5.4によると( 現在のドラフト ):

構文的に正しく、「...」が抽象宣言子の一部ではない場合、「、...」は「...」と同義です。

要するに、C++では...(省略記号)はそれ自体が演算子であるため、コンマなしで使用できますが、下位互換性のためにコンマの使用は保持されます。

36
kfsone

現在、これらの宣言は両方とも同じ意味を持っています。

int f(int n, ...);
int f(int n ...);

これにより、次の2つの宣言が両方とも合法であるにもかかわらず、意味が大きく異なるという問題が発生します。

template <class... T> void f(T...); // function template with parameter pack
template <class T> void f(T...);    // variadic function

C++ 11が可変個引数テンプレートを導入すると、2番目の宣言は、コンマを怠惰に省略するのではなく、プログラマーエラーである可能性がはるかに高くなります。その結果、後者を言語から削除する提案がありましたが( P0281 )、明らかに 拒否されました でした。

29
Barry

int f(int n, ...);int f(int n...);を使用すると、できるように see 、_, ..._と_..._はどちらも同じ意味になります。カンマはオプションです。

ただし、このint printz(...);は_C++_で有効ですが、int printz(,...);は無効です(少なくとも1つの名前付きパラメーターが省略記号パラメーターの前に表示される必要があります)。そのため、そのような関数に渡された引数にアクセスできない場合でも、_(...)_だけを持つことができます。

15
hlscalon

当時から思い出したように、C++は、お気づきのように、可変個引数関数の符号を実際に定義しました。その後、急速に進化するC言語(K&RからANSIへの道のり)で、プロトタイプまたは新しいスタイルの関数が導入されました関数名の後にparens内のパラメーターも宣言する宣言。ただし、2つの顕著な違いがあります。省略記号の前のコンマと、空のパラメータリストを示すための(void)の忌まわしさの必要性(空の親の下位互換性をold style宣言)。

アーカイブを調べてみると、C++プログラミング言語のオリジナル版「1987年7月に修正を加えて転載」は次のようになっています。

引数-宣言-リスト:
arg-declaration-listopt
...opt

arg-declaration-list:
arg-declaration-list
, 引数宣言
引数-宣言

オプションのコンマを受け入れるためのフォームなしがあります。 arg-declaration-listはコンマ-separatedであり、これはリストの後、次の(異なる)ものの前にコンマを提供するためにたむろしないことに注意してください。

これはこれを書くための最も自然な方法です。カンマが必要な場合、最初のプロダクションでは、2つの異なる(空白で区切られた)トークンとして明示的に, ...が必要です。

適切な標準化へのCの取り組みが進むにつれて、C++コンパイラはCバージョンも受け入れ始め、C標準ヘッダーファイルを簡単に使用できるようになりました。

偽のパラメータープレースホルダーとしての楕円の文法的な役割があまり意味がないことを意味するのに、Cデザイナーがコンマを追加したのはなぜですか?私は知りませんでした。

6
JDługosz