3

私は Variadic Templates に関する新しい C++11 機能を研究しているので、funテンプレート関数を書きました:

template <typename T>
void fun(T& a) //Base to stop the recursion
{
  std::cout << a;
};

template <typename... Types>
void fun(Types... args)
{
  fun(args...);
};

main テンプレートは正常にコンパイルされますが、何か を書いたときfun(1,10.232,1232);Segmentation fault. なぜこれが起こるのか、誰かが私に説明できますか?

4

1 に答える 1

6

seg-faults についてはわかりませんが、基本関数を呼び出すことはありません。各呼び出しの後にパラメーター リストを縮小する必要があります。

template <typename T>
void fun(T& a) //Base to stop the recursion
{
    std::cout << a;
};

template <typename First, typename... Types>
void fun(First arg, Types... args)
{
    fun(args...); // recursion on args... (one smaller than what was passed in).
};

基本ケースは参照によってバインドされますが、呼び出しサイトで一時オブジェクトを渡しているため、これはお勧めできません。これはおそらくあなたのセグフォルトの原因です。関数を const 参照または値によって受け入れるように変更します。

また、上記のコードはコンパイルしていないため、パラメーターを 1 つだけ指定して fun を呼び出すと、あいまいな状況になる可能性があることに注意してください。これを修正するには、引数を受け入れないように基本ケースを変更します。

void fun()
{
    // base case: no items.
}

template <typename First, typename... Rest>
void fun(First first, Rest... rest)
{
    // one or more items (the param pack is allowed to be emoty.)
    fun(rest...);
}

または、2 つ以上の引数を受け入れるように再帰的オーバーロードを変更します。

// Exactly one argument.
template <typename T>
void fun(T a)
{
    std::cout << a;
};

// Two or more arguments.
template <typename First, typename Second, typename... Rest>
void fun(First first, Second second, Rest... rest)
{
    // one or more items (the param pack is allowed to be emoty.)
    fun(second, rest...);
}

いずれにせよ、複数の関数テンプレートが拡張の候補となるケースを避けるようにしてください。そうすれば、多くの頭痛の種を回避できます。言い換えれば、すべてのオーバーロードは相互に排他的でなければなりません。

于 2013-05-22T13:14:56.603 に答える