🙆‍♀️

[C++]可変長引数の使い方を理解する

2023/01/14に公開
2

今日はC++の可変長引数の使い方を理解すべく、色々と勉強したので内容をまとめてみた。

実装をしているとたまに関数に渡す引数の数を呼び出す際に好きに変えれたらよいなと思うことがある。例えば以下のようにsumという関数がある場合、これに対して3個の引数を渡したいこともあれば10個の引数を渡したいこともある。

sum(1,2,3);
sum(1,2,3,4,5,6,7,8,9,10);

引数の数に応じたsum関数をそれぞれ定義してあげるという方法もあるが、それだと面倒。
このような場合に可変長引数が使える。

// 関数定義側
template<typename... Args>
int sum(Args... args)
{
    int s = 0;
    for(int i : std::initializer_list<int>{args...}){
        s += i;
    }
    return s;
}

// 呼び出し側
int result1 = sum(1,2,3);     // result: 6
int result2 = sum(1,2,3,4,5); // result: 15

Args... argsという仮引数宣言によって、関数呼び出し時の第2引数以降に指定された実引数は全てこのargsという仮引数に集約される。
Args... argsは配列ではないのでfor文でそのまま処理はできないため、initializer_listを用いて処理をしているが、以下のようにsizeofを使うことで可変長引数の長さを取得しforで処理することもできる。

// forを使って可変長引数を処理する場合
// 関数定義側
template<typename... Args>
int sum(Args... args)
{
    int s = 0;
    uint8_t length = sizeof...(args);
    int ary[] = { args... };
    for(int i = 0;i < length;i++)
    {
        s += ary[i];
    }
  return s;
}

// 呼び出し側
int result1 = sum(1,2,3);     // result: 6
int result2 = sum(1,2,3,4,5); // result: 15

sizeof...という書き方をすることで引数の数を取得できるため、この回数分forで処理できる。

今回の可変長引数についての詳細な内容はこちらを参考にさせて頂いた。
https://cpprefjp.github.io/lang/cpp11/variadic_templates.html

Discussion

devemindevemin

参考になる記事をありがとうございます~!

2個目のコードに return s; が足りないように思いました。失礼しました~

meloQmeloQ

コメントありがとうございます。
コードの指摘ありがとうございます!修正しておきます。