С функцией a, принимающей 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);
Почему вторая форма не работает? Или я что-то не так делаю?
Редактировать:
Из реализации 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 не может поддерживаться компилятором (?).
i
это не initializer_list
, initializer_list
не является сокращением для «статического массива». Это специальный объект, который может быть создан только (вне конструкции копирования) с помощью списка фигурных скобок (например: {...}
синтаксис).
Когда вы делаете int i[] = {...};
вы выполняете агрегатную инициализацию на массив. i
это массив int
с не initializer_list
,
То, что вы хотите, это шаблонная функция, которая может принимать все, что вы можете использовать на основе диапазона для более:
template<typename Rng>
int sumOf(const Rng &numberRange) {
int sum = 0;
for (auto x : numberRange) {
sum += x;
}
return sum;
}
Вы можете сделать трюк с индексным кортежем, как раньше использовали многие
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);
});