4

が C++0x のパックされたテンプレート引数リストの型の数を生成することは承知していsizeof...(Args...)ますが、デモンストレーション目的で他の機能に関してそれを実装したかったのですが、コンパイルされません。

// This is not a solution -- overload ambiguity.
// template <typename... Args> size_t num_args ();          // Line 7
// template <>
constexpr size_t num_args ()
{
    return 0;
}

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

int main ()
{
    std :: cout << num_args <int, int, int> ();
}

*HERE*でのこのエラー

No matching function call to ...
... candidate is template<class H, class ... T> size_t num_args()

つまり、最初に定義された基本ケースが表示されません。前方宣言template<typename...T>num_args();は、オーバーロードの解決にあいまいさをもたらします。

x.cpp:30:45: note: candidates are:
x.cpp:7:36: note: size_t num_args() [with Args = {int, float, char}, size_t = long unsigned int]
x.cpp:16:9: note: size_t num_args() [with H = int, T = {float, char}, size_t = long unsigned int]

gcc 4.6 を使用しています。どうすればこれを機能させることができますか?

ありがとう。

4

2 に答える 2

8

基本ケースを宣言しませんでした。関数のテンプレートなしのオーバーロードがありますnum_argsが、関数を呼び出すと、num_args<T...>()明らかな理由でこれが見つかりません。常に関数templateをインスタンス化しようとします。

ただし、関数テンプレートを特殊化して、目的の操作を実行することはできます。

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

ただし、ここではパラメーターなしの関数テンプレートを特殊化しており、そのようなテンプレートは存在しないため、これも機能しません。他の関数テンプレートnum_argsには常に少なくとも 1 つの引数H.

これを実際に機能させるには、部分的な特殊化が必要です。これらはクラス テンプレートに対してのみ存在します。だから、これはあなたがここで必要なものです。

template <typename T>
struct num_args_t;

template <>
struct num_args_t {
    static size_t const value = 0;
};

template <typename H, typename T...>
struct num_args_t {
    static size_t const value = num_args_t<T...>::value + 1;
};

template <typename T...>
constexpr size_t num_args() {
    return num_args_t<T...>::value;
}
于 2011-08-18T13:32:56.733 に答える
4

Konradの答えはうまくいくはずですが、そのようなものが通常表現されるより慣用的な方法は静的メンバー定数を使用することだと思うので、その解決策を提示したかっただけです。

#include <type_traits>

template <typename...> struct arg_size;  // no primary definition needed

template <typename T, typename ...Args> struct arg_size<T, Args...>
  : public std::integral_constant<std::size_t, 1 + arg_size<Args...>::value> { };

template <> struct arg_size<>
  : public std::integral_constant<std::size_t, 0> { };

次に、を介して引数パックのサイズを取得しますarg_size<Args...>::value

于 2011-08-18T13:37:14.193 に答える