可変長引数
関数が任意の数の追加引数を受け入れることを可能にする。
関数のパラメーターリストの最後のパラメーターが省略符号 (...) である場合、その関数は可変引数である。
| 省略符号の前のコンマは省略できる。 | (C++26で非推奨) |
// the function declared as follows int printx(const char* fmt, ...); int printx(const char* fmt...); // same as above, but deprecated since C++26 // may be called with one or more arguments: printx("hello world"); printx("a=%d b=%d", a, b); int printy(..., const char* fmt); // error: ... can only be the last parameter int printz(...); // valid, but the arguments cannot be accessed portably
|
これは、パラメーター単独で省略符号であるのではなく、パラメーター宣言子の一部である省略符号によって示される関数のパラメーターパック展開とは異なる。パラメーターパック展開と「可変引数」省略符号の両方は、std::is_functionの場合のように、関数テンプレートの宣言に現れることがある。 |
(C++11以降) |
目次 |
[編集] デフォルト引数の昇格
可変引数関数が呼び出されると、lvalue-to-rvalue、array-to-pointer、function-to-pointerの変換の後、可変引数リストの一部である各引数には、デフォルト引数の昇格として知られる追加の変換が適用される
|
(C++11以降) |
非PODクラス型(C++11まで)スコープ付き列挙型と、適格な非自明なコピーコンストラクタ、適格な非自明なムーブコンストラクタ、または非自明なデストラクタを持つクラス型(C++11以降)は、実装定義のセマンティクスを持つ潜在的に評価される呼び出しで条件付きでサポートされる (これらの型は未評価の呼び出しでは常にサポートされる)。
可変引数パラメーターはオーバーロード解決の目的で最も低いランクを持つため、SFINAEにおいて、すべてをキャッチするフォールバックとして一般的に使用される。
可変引数を使用する関数の本体内で、これらの引数の値は<cstdarg> ライブラリ機能を使用してアクセスできる。
| ヘッダー
<cstdarg> で定義 | |
| 可変長引数関数へのアクセスを有効にする (関数マクロ) | |
| 次の可変長引数にアクセスする (関数マクロ) | |
| (C++11) |
可変長引数のコピーを作成する (関数マクロ) |
| 可変長引数の走査を終了する (関数マクロ) | |
| va_start, va_arg, va_end, va_copy で必要となる情報を保持します。 (typedef) | |
va_start マクロの動作は、省略符号の直前の最後のパラメーターが参照型である場合、またはデフォルト引数の昇格によって生じる型と互換性のある型でない場合は未定義である。
|
va_startの最後のパラメーターとしてパック展開、またはラムダキャプチャの結果のエンティティが使用された場合、プログラムは不適格であり、診断は不要である。 |
(C++11以降) |
[編集] 代替手段
|
(C++11以降) |
[編集] 備考
Cプログラミング言語ではC23まで、少なくとも1つの名前付きパラメーターが省略符号パラメーターの前に現れる必要があり、R printz(...); はC23までは無効であった。C++では、この形式は許可されているが、このような関数に渡される引数にはアクセスできず、オーバーロード解決における省略符号変換の最も低い優先順位を利用して、SFINAEのフォールバックオーバーロードとして一般的に使用される。
可変引数に対するこの構文は、1983年のC++で、省略符号の前のコンマなしで導入された。C89がC++から関数プロトタイプを採用した際、コンマを必須とする構文に置き換えた。互換性のために、C++98はC++スタイルのf(int n...)とCスタイルのf(int n, ...)の両方を受け入れる。元のC++スタイルの文法はC++26以降非推奨である。
|
コンマは、省略形関数テンプレートで使用され、省略符号が可変引数テンプレートではなく可変引数関数を示すようにすることができる。 void f1(auto...); // template<class... Ts> void f3(Ts...) と同じ |
(C++20以降) |
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 506 | C++98 | 非PODクラス引数を 省略符号に渡すと未定義動作になった |
そのような引数を渡すことは 実装定義のセマンティクスで 条件付きでサポートされる |
| CWG 634 | C++98 | 条件付きでサポートされるクラス型によって SFINAEイディオムの一部が動作しなくなった |
未評価の場合、常にサポートされる |
| CWG 2247 | C++11 | パラメーターパックやラムダキャプチャを va_start に渡すことに対する制限がなかった |
不適格になったが、 診断は不要 |
| CWG 2347 | C++11 | 省略符号に渡されるスコープ付き列挙型がデフォルト引数の昇格の対象となるか どうか不明確だった |
スコープ付き列挙型を渡すことは 条件付きでサポートされる 条件付きでサポートされる |
[編集] 関連項目
| C ドキュメント - 可変引数
| |
| C ドキュメント - 暗黙の型変換
|