0

以下に示すように、 std::initializer_list を引数として取る関数

int sumOf(std::initializer_list<int> numbers) {
    int sum = 0;  
    for (auto x : numbers) {
        sum += x;
    }
    return sum;
}

このコードは機能します

auto sum = sumOf({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });

しかし、これではありません

 int i[]  = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 auto x = sumOf(i);

2 番目の形式が機能しないのはなぜですか? それとも私は何か間違ったことをしていますか?

編集:
std::intializer_list の gcc 4.7.2 実装から、intializer_list のコンストラクターはプライベートであり、コンパイラーは配列のサイズを渡す必要があります。

  // The compiler can call a private constructor.
  constexpr initializer_list(const_iterator __a, size_type __l)
  : _M_array(__a), _M_len(__l) { }

コンパイラが変数「i」から配列のサイズを判断できない場合があると思います。その場合、静的配列を intializer_list に渡すことは、コンパイラによってサポートされません (?)。

4

2 に答える 2

2

iではありませんinitializer_listinitializer_list「静的配列」の省略形ではありません。{...}これは、波括弧初期化リスト (つまり、構文)を使用することによってのみ (コピー構築の外で) 作成できる特別なオブジェクトです。

これを行うと、配列int i[] = {...};で集計の初期化を実行しています。はではなく、 の配列です。iintinitializer_list

あなたが望むのはテンプレート関数です。これは、range-based-for で使用できるものなら何でも取ることができます。

template<typename Rng>
int sumOf(const Rng &numberRange) {
    int sum = 0;  
    for (auto x : numberRange) {
        sum += x;
    }
    return sum;
}
于 2012-12-06T08:21:21.580 に答える
1

以前に多くの人が使用していたように、インデックス タプル トリックを実行できます。

template<int N, int ...X>
struct I : struct I<N-1, N, X...> {};

template<int X...>
struct I<0, X...> {
  typedef I type;
};

template<typename F, typename T, int N, int ...X>
decltype(f(std::declval<std::initializer_list<T>>()))
make_list(T const (&a)[N], F f, I<X...>) 
{
   return f(std::initializer_list<T>{a[X]...});
}

template<typename F, typename T, int N>
decltype(f(std::declval<std::initializer_list<T>>()))
make_list(T const(&a)[N], F f) {
   return make_list(a, f, typename I<N-1>::type());
}

使い方は簡単

make_list(i, &sumOf);

またはラムダを使用して

make_list(i, [](std::initializer_list<int> x) {
  return sumOf(x);
});
于 2012-12-06T15:41:07.460 に答える