重複の可能性:
C++ の可変数の引数?
引数の数が可変の関数の引数の数を設定できませんか? 例として、次のインターフェースを実装できますか?
int sum(...) { ... }
sum(1, 2, 3, 4); // return 10
重複の可能性:
C++ の可変数の引数?
引数の数が可変の関数の引数の数を設定できませんか? 例として、次のインターフェースを実装できますか?
int sum(...) { ... }
sum(1, 2, 3, 4); // return 10
従来の可変個引数関数は面倒でタイプ セーフではありませんが、C++11 では可変個引数テンプレートと (コンパイル時の) 再帰を使用してこれをきれいに行うことができます。
// Base case for recursion
template <typename T>
inline T sum(T n) {
return n;
}
// Recursive case
template <typename T, typename... Args>
inline T sum(T n, Args... args) {
return n + sum(args...);
}
これはテンプレートであるため、次のようにoperator+
定義されているすべてのタイプで機能します。
std::cout << sum(1, 2, 3) << std::endl; // Prints 6
std::cout << sum(3.14, 2.72) << std::endl; // Prints 5.86
ただし、再帰テンプレート関数の戻り値の型は最初の引数のみから取得されるため、1 回の呼び出しで異なる引数の型を混在させると、驚くべき結果が得られます。 sum(2.5, 2)
期待どおり 4.5 が返されsum(2, 2.5)
ますが、戻り値の型がint
であるため 2 が返されますdouble
。派手にしたい場合は、新しい代替関数構文を使用して、戻り値の型が の自然な型であることを指定n + sum(args...)
できます。
// Recursive case
template <typename T, typename... Args>
inline auto sum(T n, Args... args) -> decltype(n + sum(args...)) {
return n + sum(args...);
}
現在sum(2.5, 2)
、sum(2, 2.5)
両方とも 4.5 を返します。
実際のロジックが合計よりも複雑で、インライン化したくない場合は、インライン テンプレート関数を使用して、すべての値をある種のコンテナー ( astd::vector
または などstd::array
) に入れ、それを非インラインに渡すことができます。最後に実際の作業を行う関数。
vector<int>
おそらくこれを行うには、波括弧付きの初期化子リストを使用してオンザフライで構築するa のようなものを取る関数を記述します。
int sum(std::vector<int> const &n) {
return std::accumulate(begin(n), end(n), 0);
}
数値が(たとえば)代わりに浮動小数点である可能性がある場合は、代わりにテンプレートとして書きたいと思うでしょう:
template <class T>
T sum(std::vector<T> const &n) {
return std::accumulate(begin(n), end(n), T());
}
いずれにせよ、これをわずかに異なる方法で呼び出すことになります。
int x = sum({1,2,3,4});
警告: この機能はかなり最近 C++ に追加されたため、一部のコンパイラ (VC++ など) はまだサポートしていませんが、他のコンパイラ (g++ 4.7+ など) はサポートしています。
いいえ、できません。
可変引数を使用しないでください。彼らは考えられるありとあらゆる方法を吸収し、誰の時間にもまったく価値がありません。
C++ 可変個引数関数は、渡された引数の数 (および型) を認識している必要があります。たとえば、printf のフォーマット文字列は、期待される追加の引数を示します。
4 つの int を取得したか 10 を取得したかを知る方法sum
はありません。最初の引数を長さにすることができます。
int sum(int howmany, ...) { ... }
そのため、関数は int がいくつ続くかを知っています。しかし、実際には、配列 (または C++ っぽい場合はベクトル) を渡す必要があります。
問題を解決するには複数の方法があります。いくつか説明します。
方法 1: -必要に応じて一連のオーバーロードされた合計関数を作成します。
短所 - コードの肥大化
これは、ヘッダーを使用して複数の関数を作成することで実装できます。
int sum(int a);
int sum(int a, int b);
int sum(int a, int b, int c);
等...
方法 2: - リンク リストを使用してカスタム クラスを作成し、リンク リストの先頭へのポインターを渡します。渡されるデータの量がわからない場合は、これがおそらく最善の方法です。
関数ヘッダー:
int sum(LinkedList *headPointer);
方法 3: -変数の配列を渡す
関数ヘッダー:
int sum(int input[]);
方法 4: -自動設定変数を使用して関数を作成する
関数ヘッダー:
int sum(int a=0, int b=0, int c=0, int d=0,... int n=0);