19

たとえばここstdarg.hで説明されているように、C ++で可変引数を持つ関数を使用する方法を既に知っています。また、ここで説明されているように、c++ 11 標準には可変個引数テンプレートがあることも知っています。

しかし、前述の両方のスキームでは、コンパイル時の引数の型がわかりません (強制することもできません)。私が探しているのは、既知の型の可変引数を関数に渡すことです。ここでそれについて読んだので、これができると思います:

可変数の引数をとる関数を作成するためにも使用できる可変個引数テンプレートは、引数の型に制限を課さず、整数および浮動小数点の昇格を実行せず、型安全であるため、多くの場合、より良い選択です。 .

出来ますか?はいの場合、どうすればこれを行うことができますか?

4

2 に答える 2

30

任意の数の引数を受け入れる可変個引数テンプレートを使用して関数を作成するのは簡単です。一般的なパターンとの唯一の違いは、具体的な型がテンプレート パラメーターの代わりに最初の引数 (ヘッド) として使用されることです。foobar次の例は、任意の数の文字列を受け入れる関数を示しています。

// used for end of recursion - and for the empty arguments list
void foobar() { }

template <typename ...Tail>
void foobar(const std::string& head, Tail&&... tail)
{
    // do something with head
    std::cout << head << '\n';
    // call foobar recursively with remaining arguments
    foobar(std::forward<Tail>(tail)...);
}

foobar("Hello", "World", "...");

個人的にstd::initializer_listは、可変個引数テンプレートの代わりに使用することを好みます。可変個引数テンプレートはより複雑で、追加の経験が必要になるためです。ではstd::initializer_list、次のようになります。

void foobar(std::initializer_list<std::string> values)
{
    for (auto& value : values) {
        // do something with value
        std::cout << value << '\n';
    }
}

foobar({ "Hello", "World", "...", });

std::initializer_list残念ながら、通常の関数で使用する場合は、中括弧を追加する必要があります。新しいイニシャライザ構文が使用されている場合、コンストラクタには必要ありません。

編集:フィードバックに従って回答を書き直しました。特に、2 つのソリューション/例の順序を変更しました。

于 2012-04-06T14:21:36.190 に答える
2

変数パラメーターがすべて1つのタイプである場合、「...」を使用する代わりに、関数のシグネチャを変更して、それらのタイプの配列を取得できます。

于 2012-04-06T14:02:28.053 に答える