3

これは私の以前の投稿に関連しています。試みた 1 つの解決策がうまくいかなかった理由を知りたいです。

template <typename... T>             /* A */
size_t num_args ();

template <>
size_t num_args <> ()
{
    return 0;
}

template <typename H, typename... T> /* B */
size_t num_args ()
{
    return 1 + num_args <T...> ();
}

たとえば、呼び出そうとするとnum_args<int,float>()、関数呼び出しがあいまいであるというエラーが表示されます。

  • T={int,float} の A
  • H=int、T={float} の B

これがあいまいである理由がわかりません。A は宣言であり、B は A によって宣言された関数の定義です。

私はこの例を機能させようとしていますが、以前の質問への回答は、決して機能しないと主張しているようです。

その場合、可変長自由関数のポイントは何ですか? 彼らは何ができますか?

4

3 に答える 3

7

これがあいまいである理由がわかりません。A は宣言であり、B は A によって宣言された関数の定義です。

A は関数テンプレートの宣言であり、B は別の関数テンプレートの宣言 (および定義) です。

コンパイラは 2 つのどちらかを決定する方法がありません: どちらも引数を持たず、テンプレート引数は両方に一致します。

真ん中のものは、A で宣言された関数テンプレートの明示的な完全特殊化です。

B を A の別の特殊化にしようとした場合:

template <typename H, typename... T> /* B */
size_t num_args<H, T...>()
{
    return 1 + num_args <T...> ();
}

... 関数テンプレートの部分的な特殊化になってしまいますが、これは許可されていません。

これは、部分的な特殊化を含むクラス テンプレートと、クラス テンプレートを呼び出す関数テンプレートを使用する通常のトリックで実行できます。

template <typename... T>
class Num_Args;

template <>
struct Num_Args <>
{
    static constexpr size_t calculate() {
        return 0;
    }
};

template <typename H, typename... T>
struct Num_Args <H, T...>
{
    static constexpr size_t calculate() {
        return 1 + Num_Args<T...>::calculate();
    }
};

template <typename... T> /* B */
constexpr size_t num_args ()
{
    return Num_Args<T...>::calculate();
}
于 2011-08-18T15:53:36.770 に答える
4

無料の可変個引数関数テンプレートの有用性/無用性に適しています: これらの通常の使用例は、可変個引数関数のパラメーター リストを持つことです。この場合、空のケースの通常のオーバーロードは問題なく機能します。

size_t num_args()
{
    return 0;
}

template <typename H, typename... T> /* B */
size_t num_args (H h, T... t)
{
    return 1 + num_args(t...);
}


編集:

私が見る限り、次の悪用はenable_ifあなたの元の質問に対する解決策として機能するはずです:

#include <utility>

// Only select this overload in the empty case 
template <typename... T>
typename std::enable_if<(sizeof...(T) == 0), size_t>::type
num_args() 
{ 
    return 0;
}

template <typename H, typename... T>
size_t
num_args() 
{
    return 1 + num_args<T...>();
}

(Edit2: コードを実際にコンパイルするために、オーバーロードの順序を逆にしました)

于 2011-08-19T09:16:34.567 に答える