19

符号なし整数を単純に受け入れる可変個引数テンプレートが必要です。ただし、次の作業を行うことができませんでした。

struct Array
{
    template <typename... Sizes> // this works
    // template <unsigned... Sizes> -- this does not work (GCC 4.7.2)
    Array(Sizes... sizes)
    {
        // This causes narrowing conversion warning if signed int is supplied.
        unsigned args[] = { sizes... };
        // ...snipped...
    }
};

int main()
{
    Array arr(1, 1);
}

どんな助けでも感謝します。

編集: ご参考までに、私は可変個引数テンプレートを使用して以下を複製しようとしています。

struct Array
{
    Array(unsigned size1) { ... }
    Array(unsigned size1, unsigned size2) { ... }
    Array(unsigned size1, unsigned size2, unsigned size3) { ... }
    // ...
    Array(unsigned size1, unsigned size2, ..., unsigned sizeN) { ... }
};
4

4 に答える 4

8

すべて整数でなければならない動的引数を受け入れたい場合は、通常の型名テンプレートが必要ですが、すべての型が (変換可能な) 符号なし整数であることを確認してください。

#include <type_traits>

struct Array
{
    template <typename ...Args>
    explicit Array(Args ...args,
        typename std::enable_if<all_int<Args...>::value>::type * = nullptr);

    // ...
};

あとは特性だけが必要です:

template <typename...> struct all_int;

template <> struct all_int<> : std::true_type { };

template <typename T, typename ...Rest> struct all_int<T, Rest...>
: std::integral_constant<bool,
       std::is_convertible<T, unsigned int>::value && all_int<Rest>::value>
{ }

型を厳密にしたい場合は、is_same代わりに を使用することもできますis_convertible

別のオプションは、可変個引数テンプレートを完全に放棄し、単一std::initializer_list<unsigned int>の を受け入れることでクラスをリスト初期化可能にすることです。これにより、数値の安全性が大幅に向上します (たとえば、縮小変換は禁止されます)。

于 2012-11-29T23:09:28.677 に答える
8

なぜそれがうまくいくと期待したのかわかりません。Clang は、エラーがunknown type name 'Sizes'コンストラクターの宣言にあることを教えてくれます。Sizes型 (または、型のテンプレート パック) ではないため、値のテンプレート パックであるため、これは当然のことです。

ここで何をしようとしているのか正確には不明です。整数値をテンプレート パラメーターとして渡す場合、コンストラクター パラメーターは何になるはずですか?


更新: 新しいコードで必要なのはstatic_cast<unsigned>().

struct Array
{
    template <typename... Sizes> // this works
    Array(Sizes... sizes)
    {
        unsigned args[] = { static_cast<unsigned>(sizes)... };
        // ...snipped...
    }
};
于 2012-11-29T23:00:41.950 に答える
5

初期化リストを調べる

次のように指定できます

struct Array
{
    Array(std::initializer_list<unsigned> sizes)
    {
        for (auto i = sizes.begin(); i != sizes.end(); ++i)
            ...
    }
}

ただし、使用方法は次のように変更されます

Array arr = {1, 1};
于 2012-11-29T23:11:30.323 に答える