名前空間
変種
操作

可変長引数

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定(C++20未満)
noexcept 指定子(C++11)
例外
名前空間
指定子
decltype(C++11)
auto(C++11)
alignas(C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr(C++11)
ユーザ定義(C++11)
ユーティリティ
属性(C++11)
typedef 宣言
型エイリアス宣言(C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

関数が任意個の引数を受け取ることを可能とします。

関数宣言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_tvoid* に変換されます。
  • float の引数は浮動小数点昇格の場合と同様に double に変換されます。
  • boolcharshort、およびスコープなし列挙は整数昇格の場合と同様に int またはより幅の広い整数型に変換されます。

算術、列挙、ポインタ、メンバへのポインタ、およびクラス型の引数のみが使用できます (非トリビアルなコピーコンストラクタ、非トリビアルなムーブコンストラクタ、または非トリビアルなデストラクタを持つクラスは除きます (これらは処理系定義の意味論で条件的にサポートされます))。

可変長引数はオーバーロード解決の目的に対して最も低い順位であるため、 SFINAE で全捕獲のフォールバックとしてよく使用されます。

可変長引数を使用する関数の本体内では、それらの引数の値は <cstdarg> ライブラリの機能を用いてアクセスできます。

ヘッダ <cstdarg> で定義
可変長引数関数の引数にアクセスできるようにします
(関数マクロ)[edit]
可変長引数関数の次の引数にアクセスします
(関数マクロ)[edit]
(C++11)
可変長引数関数の引数のコピーを作成します
(関数マクロ)[edit]
可変長引数関数の引数のトラバーサルを終了します
(関数マクロ)[edit]
va_start, va_arg, va_end, va_copy によって必要とされる情報を保持します
(typedef)[edit]

省略記号の前の最後の引数が参照型またはデフォルト引数昇格の結果の型と互換性のない型の場合、 va_start マクロの動作は未定義です。

[編集]代替手段

  • 可変長引数テンプレートも可変個の引数を取る関数を作成するために使用できます。 これらは引数の型に対する制約を課さず、整数昇格および浮動小数点昇格を行わず、型安全であるため、しばしばより良い選択です。
  • すべての可変長引数が共通の型を共有する場合、 std::initializer_list は可変長引数にアクセスするための便利な仕組みを提供します (用いる構文は異なりますが)。 しかし、この場合、 std::initializer_list は要素への const ポインタを提供するだけであるため、引数は変更できません。
(C++11以上)

[編集]ノート

C プログラミング言語では、省略記号引数の前に少なくとも1個の名前付き引数が現れなければならないため、 printz(...); は有効ではありません。 C++ では、たとえ渡された引数がアクセス可能でなくとも、この形式は許容されており、オーバーロード解決における省略記号変換の優先順位が最も低いことを利用して、 SFINAE でフォールバックオーバーロードとしてよく使用されます。

可変長引数のための構文は省略記号の前のコンマなしで1983年の C++ で導入されました。 C89 が C++ から関数プロトタイプを採用したとき、構文はコンマを要求するものに置き換えられました。 互換性のため、 C++98 は C++ スタイルの f(int n...) と C スタイルの f(int n, ...) をどちらも受理します。

[編集]関連項目

可変長引数C言語リファレンス
close