我可以使用 std::initializer_list 而不是大括号括起来的初始化程序来初始化数组吗?
Can I initialize an array using the std::initializer_list instead of brace-enclosed initializer?
我可以使用 std::initializer_list
对象而不是大括号括起来的初始化程序来初始化数组吗?
众所周知,我们可以这样做:http://en.cppreference.com/w/cpp/language/aggregate_initialization
unsigned char b[5]{"abc"};
// equivalent to unsigned char b[5] = {'a', 'b', 'c', '[=11=]', '[=11=]'};
int ar[] = {1,2,3};
std::array<int, 3> std_ar2{ {1,2,3} }; // std::array is an aggregate
std::array<int, 3> std_ar1 = {1, 2, 3};
但我无法通过 std::initializer_list il;
初始化数组:
#include <iostream>
#include <initializer_list>
#include <array>
int main() {
int arr1[] = { 1, 2, 3 }; // OK
std::array<int, 3> arr2 = { 1, 2, 3 }; // OK
std::initializer_list<int> il = { 1, 2, 3 };
constexpr std::initializer_list<int> il_constexpr = { 1, 2, 3 };
//int arr3[] = il; // error
//int arr4[] = il_constexpr; // error
//std::array<int, 3> arr5 = il; // error
//std::array<int, 3> arr6 = il_constexpr; // error
return 0;
}
但是如何使用std::initializer_list il;
初始化一个数组呢?
据我所知,不:你不能用 std::initializer_list
.
初始化 std::array
问题在于 std::array
旨在作为 classic C 样式数组的轻量级替代品(包装器)。如此之轻,没有构造函数,所以只能使用隐式构造函数。
具有聚合初始化的构造(通过隐式构造函数)是可能的,因为它可能用于 C 样式数组。
但是 std::initializer_list
是一个 class,比聚合初始化更复杂。
例如,您可以用 std::initializer_list
初始化 std::vector
,但这只是因为 std::vector
有一个接收 std::initializer_list
的显式构造函数。但是 std::vector
比较重 class.
我看到的唯一解决方案是两步法:(1) 构造和 (2) std::initializer_list
值的副本。像
std::array<int, 3> arr5;
auto ui = 0U;
auto cit = il.cbegin();
while ( (ui < arr5.size()) && (cit != il.cend()) )
arr5[ui++] = *cit++;
p.s.: 抱歉我的英语不好
std::array
的问题在于它必须是 聚合 类型,因此它没有构造函数。
因此只能进行聚合初始化或简单复制。
std::initializer_list
是 class 而不是 std::array
,因此需要(缺少)隐式转换。
见http://en.cppreference.com/w/cpp/language/aggregate_initialization
http://en.cppreference.com/w/cpp/container/array
供参考。
其他回答正确的人说这是不可能的。但是有了小帮手,你可以很接近
template<typename T, std::size_T N, std::size_t ...Ns>
std::array<T, N> make_array_impl(
std::initializer_list<T> t,
std::index_sequence<Ns...>)
{
return std::array<T, N>{ *(t.begin() + Ns) ... };
}
template<typename T, std::size_t N>
std::array<T, N> make_array(std::initializer_list<T> t) {
if(N > t.size())
throw std::out_of_range("that's crazy!");
return make_array_impl<T, N>(t, std::make_index_sequence<N>());
}
如果您愿意接受更多变通方法,可以将其放入 class 中,以便在传递花括号初始化列表的情况下捕获静态已知的长度违规。但请注意,大多数阅读此代码的人都会在 head-desk
template<typename T, std::size_t N>
struct ArrayInitializer {
template<typename U> struct id { using type = U; };
std::array<T, N> t;
template<typename U = std::initializer_list<T>>
ArrayInitializer(typename id<U>::type z)
:ArrayInitializer(z, std::make_index_sequence<N>())
{
if(N > z.size())
throw std::out_of_range("that's crazy!");
}
template<typename ...U>
ArrayInitializer(U &&... u)
:t{ std::forward<U>(u)... }
{ }
private:
template<std::size_t ...Ns>
ArrayInitializer(std::initializer_list<T>& t,
std::index_sequence<Ns...>)
:t{ *(t.begin() + Ns) ... }
{ }
};
template<typename T, std::size_t N>
std::array<T, N> f(ArrayInitializer<T, N> ai) {
return std::move(ai.t);
}
int main() {
f<int, 5>({1, 2, 3, 4, 5}); // OK
f<int, 5>({1, 2, 3, 4, 5, 6}); // "too many initializers for array<int, 5>"
std::initializer_list<int> il{1, 2, 3, 4, 5};
f<int, 5>(il); // ok
}
请注意,答案顶部的非静态情况和 "head-desk" 情况都只检查您提供的初始化元素是否太少,然后出现错误,initializer_list
案件。如果您为 initializer_list
案例提供了太多,则尾随元素将被忽略。
我可以使用 std::initializer_list
对象而不是大括号括起来的初始化程序来初始化数组吗?
众所周知,我们可以这样做:http://en.cppreference.com/w/cpp/language/aggregate_initialization
unsigned char b[5]{"abc"};
// equivalent to unsigned char b[5] = {'a', 'b', 'c', '[=11=]', '[=11=]'};
int ar[] = {1,2,3};
std::array<int, 3> std_ar2{ {1,2,3} }; // std::array is an aggregate
std::array<int, 3> std_ar1 = {1, 2, 3};
但我无法通过 std::initializer_list il;
初始化数组:
#include <iostream>
#include <initializer_list>
#include <array>
int main() {
int arr1[] = { 1, 2, 3 }; // OK
std::array<int, 3> arr2 = { 1, 2, 3 }; // OK
std::initializer_list<int> il = { 1, 2, 3 };
constexpr std::initializer_list<int> il_constexpr = { 1, 2, 3 };
//int arr3[] = il; // error
//int arr4[] = il_constexpr; // error
//std::array<int, 3> arr5 = il; // error
//std::array<int, 3> arr6 = il_constexpr; // error
return 0;
}
但是如何使用std::initializer_list il;
初始化一个数组呢?
据我所知,不:你不能用 std::initializer_list
.
std::array
问题在于 std::array
旨在作为 classic C 样式数组的轻量级替代品(包装器)。如此之轻,没有构造函数,所以只能使用隐式构造函数。
具有聚合初始化的构造(通过隐式构造函数)是可能的,因为它可能用于 C 样式数组。
但是 std::initializer_list
是一个 class,比聚合初始化更复杂。
例如,您可以用 std::initializer_list
初始化 std::vector
,但这只是因为 std::vector
有一个接收 std::initializer_list
的显式构造函数。但是 std::vector
比较重 class.
我看到的唯一解决方案是两步法:(1) 构造和 (2) std::initializer_list
值的副本。像
std::array<int, 3> arr5;
auto ui = 0U;
auto cit = il.cbegin();
while ( (ui < arr5.size()) && (cit != il.cend()) )
arr5[ui++] = *cit++;
p.s.: 抱歉我的英语不好
std::array
的问题在于它必须是 聚合 类型,因此它没有构造函数。
因此只能进行聚合初始化或简单复制。
std::initializer_list
是 class 而不是 std::array
,因此需要(缺少)隐式转换。
见http://en.cppreference.com/w/cpp/language/aggregate_initialization http://en.cppreference.com/w/cpp/container/array 供参考。
其他回答正确的人说这是不可能的。但是有了小帮手,你可以很接近
template<typename T, std::size_T N, std::size_t ...Ns>
std::array<T, N> make_array_impl(
std::initializer_list<T> t,
std::index_sequence<Ns...>)
{
return std::array<T, N>{ *(t.begin() + Ns) ... };
}
template<typename T, std::size_t N>
std::array<T, N> make_array(std::initializer_list<T> t) {
if(N > t.size())
throw std::out_of_range("that's crazy!");
return make_array_impl<T, N>(t, std::make_index_sequence<N>());
}
如果您愿意接受更多变通方法,可以将其放入 class 中,以便在传递花括号初始化列表的情况下捕获静态已知的长度违规。但请注意,大多数阅读此代码的人都会在 head-desk
template<typename T, std::size_t N>
struct ArrayInitializer {
template<typename U> struct id { using type = U; };
std::array<T, N> t;
template<typename U = std::initializer_list<T>>
ArrayInitializer(typename id<U>::type z)
:ArrayInitializer(z, std::make_index_sequence<N>())
{
if(N > z.size())
throw std::out_of_range("that's crazy!");
}
template<typename ...U>
ArrayInitializer(U &&... u)
:t{ std::forward<U>(u)... }
{ }
private:
template<std::size_t ...Ns>
ArrayInitializer(std::initializer_list<T>& t,
std::index_sequence<Ns...>)
:t{ *(t.begin() + Ns) ... }
{ }
};
template<typename T, std::size_t N>
std::array<T, N> f(ArrayInitializer<T, N> ai) {
return std::move(ai.t);
}
int main() {
f<int, 5>({1, 2, 3, 4, 5}); // OK
f<int, 5>({1, 2, 3, 4, 5, 6}); // "too many initializers for array<int, 5>"
std::initializer_list<int> il{1, 2, 3, 4, 5};
f<int, 5>(il); // ok
}
请注意,答案顶部的非静态情况和 "head-desk" 情况都只检查您提供的初始化元素是否太少,然后出现错误,initializer_list
案件。如果您为 initializer_list
案例提供了太多,则尾随元素将被忽略。