可変長引数
関数が任意個の引数を受け取ることを可能とします。
関数宣言の parameter-list の後に続く末尾の ...(パック展開を導入するものを除きます)(C++11以上) によって表されます。
parameter-list が空のとき、可変長引数関数を表す ... の前にオプショナルなコンマを付けても構いません。 これは C との互換性を提供します (C は C++ から関数のプロトタイプを採用したときにコンマに対する要求を追加しました)。
// 以下のように宣言された関数は、int printx(constchar* fmt...);// 1個以上の引数を使用して呼べます。 printx("hello world"); printx("a=%d b=%d", a, b); int printx(constchar* fmt, ...);// 同上 (C との互換性のために// 余分なコンマを付けても構いません)。int printy(..., constchar* fmt);// エラー、 ... は引数として現れることはできません。int printz(...);// 有効ですが、引数はポータブルにアクセスすることはできません。
ノート: これは関数パラメータパック式とは異なります。 パラメータパック式はすべての引数宣言の後に現れる省略記号でなく引数宣言子の一部である省略記号によって示されます。 std::is_function の場合のように、パラメータパック展開と可変長引数の省略記号の両方が関数テンプレートの宣言に現れても構いません。 | (C++11以上) |
目次 |
[編集]デフォルト変換
可変長引数関数が呼ばれたとき、左辺値から右辺値、配列からポインタ、および関数からポインタへの変換の後、可変長引数リストの一部である引数は、それぞれ、デフォルト引数昇格と呼ばれる追加の変換が行われます。
- std::nullptr_t は void* に変換されます。
- float の引数は浮動小数点昇格の場合と同様に double に変換されます。
- bool、 char、 short、およびスコープなし列挙は整数昇格の場合と同様に int またはより幅の広い整数型に変換されます。
算術、列挙、ポインタ、メンバへのポインタ、およびクラス型の引数のみが使用できます (非トリビアルなコピーコンストラクタ、非トリビアルなムーブコンストラクタ、または非トリビアルなデストラクタを持つクラスは除きます (これらは処理系定義の意味論で条件的にサポートされます))。
可変長引数はオーバーロード解決の目的に対して最も低い順位であるため、 SFINAE で全捕獲のフォールバックとしてよく使用されます。
可変長引数を使用する関数の本体内では、それらの引数の値は <cstdarg> ライブラリの機能を用いてアクセスできます。
ヘッダ <cstdarg> で定義 | |
可変長引数関数の引数にアクセスできるようにします (関数マクロ) | |
可変長引数関数の次の引数にアクセスします (関数マクロ) | |
(C++11) | 可変長引数関数の引数のコピーを作成します (関数マクロ) |
可変長引数関数の引数のトラバーサルを終了します (関数マクロ) | |
va_start, va_arg, va_end, va_copy によって必要とされる情報を保持します (typedef) |
省略記号の前の最後の引数が参照型またはデフォルト引数昇格の結果の型と互換性のない型の場合、 va_start マクロの動作は未定義です。
[編集]代替手段
| (C++11以上) |
[編集]ノート
C プログラミング言語では、省略記号引数の前に少なくとも1個の名前付き引数が現れなければならないため、 printz(...);
は有効ではありません。 C++ では、たとえ渡された引数がアクセス可能でなくとも、この形式は許容されており、オーバーロード解決における省略記号変換の優先順位が最も低いことを利用して、 SFINAE でフォールバックオーバーロードとしてよく使用されます。
可変長引数のための構文は省略記号の前のコンマなしで1983年の C++ で導入されました。 C89 が C++ から関数プロトタイプを採用したとき、構文はコンマを要求するものに置き換えられました。 互換性のため、 C++98 は C++ スタイルの f(int n...) と C スタイルの f(int n, ...) をどちらも受理します。
[編集]関連項目
可変長引数 の C言語リファレンス |