1

パラメータを出力する可変個引数テンプレートを次に示します。

#include <string>
#include <iostream>

void Output() {
    std::cout<<std::endl;
}

template<typename First, typename ... Strings>
void Output(First arg, const Strings&... rest) {
    std::cout<<arg<<" ";
    Output(rest...);
}

int main() {
    Output("I","am","a","sentence");
    Output("Let's","try",1,"or",2,"digits");
    Output(); //<- I do not want this to compile, but it does.

    return 0;
}

「パラメーターなし」の呼び出しを機能させずに、毎回 2 つの関数を記述することなく、この機能を取得する方法はありますか?

4

3 に答える 3

3

最初のパラメーターと残りのパラメーターの分離を維持したい場合は、次を使用できます。

template<typename First, typename ... Rest>
void Output(First&& first, Rest&&... rest) {
    std::cout << std::forward<First>(first);
    int sink[]{(std::cout<<" "<<std::forward<Rest>(rest),0)... };
    (void)sink; // silence "unused variable" warning
    std::cout << std::endl;
}

パラメータのコピーを避けるために、完全転送を使用したことに注意してください。上記には、再帰を回避するという追加の利点があるため、より優れた (より高速な) コードを生成する可能性があります。

私が書いた方法はsink、展開された式が左から右に評価されることも保証します。restこれは、ヘルパー関数を書くだけの素朴なアプローチと比較すると重要template<typename...Args>void sink(Args&&...){}です。

実際の例

于 2013-10-27T07:11:20.740 に答える
2

私が見る限り、2つの質問があります:

  1. Output()パラメータなしの呼び出しを回避する方法。
  2. コンパイル時の再帰を終了する簡単な方法はありますか?

項目1に対する私の解決策は次のとおりです。

template<typename T>
void Output(const T & string) {
    std::cout<<string<<std::endl;
}

template<typename First, typename ... Strings>
void Output(const First & arg, const Strings & ... rest) {
    std::cout<<arg<<" ";
    Output(rest...);
}

基本的に、テンプレート リストが空のときに再帰を終了するのではなく、型が 1 つしか含まれていないときに終了します。上記と質問のコードには違いが 1 つあります。if は最後の項目の後にスペースを出力しません。代わりに、改行を出力するだけです。

質問 2 については、上記の Daniel Frey による回答を参照してください。理解するのに少し時間がかかりましたが、私はこのソリューションが本当に気に入りました(そして私は答えに賛成しました)。同時に、コードの読み取り/理解が難しくなり、保守が難しくなることがわかりました。現在、私はそのソリューションを小さな個人的なコード スニペット以外には使用しません。

于 2013-10-27T12:32:52.710 に答える