C++ 我是否可以使用std::initializer\u列表而不是括号内的initializer来初始化数组?
我是否可以使用C++ 我是否可以使用std::initializer\u列表而不是括号内的initializer来初始化数组?,c++,c++11,c++14,initializer-list,c++17,C++,C++11,C++14,Initializer List,C++17,我是否可以使用std::initializer\u list对象而不是括号内的初始值设定项来初始化数组 众所周知,我们可以这样做: 但是如何使用std::initializer\u list il初始化数组?据我所知,否:不能使用std::initializer\u list初始化std::array 问题在于std::array旨在作为经典C风格数组的轻量级替代品(包装器)。没有构造函数,所以只能使用隐式构造函数 聚合初始化的构造(通过隐式构造函数)是可能的,因为它对于C样式数组是可能的 但是
std::initializer\u list
对象而不是括号内的初始值设定项来初始化数组
众所周知,我们可以这样做:
但是如何使用
std::initializer\u list il
初始化数组?据我所知,否:不能使用std::initializer\u list
初始化std::array
问题在于std::array
旨在作为经典C风格数组的轻量级替代品(包装器)。没有构造函数,所以只能使用隐式构造函数
聚合初始化的构造(通过隐式构造函数)是可能的,因为它对于C样式数组是可能的
但是std::initializer\u list
是一个类,比聚合序列化更复杂
例如,您可以使用std::initializer\u list
初始化std::vector
,但这只是因为有一个显式构造函数,用于std::vector
,它接收std::initializer\u list
。但是std::vector
是一个较重的类
我看到的唯一解决方案是一种两步方法:(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++;
std::数组arr5;
自动用户界面=0U;
auto cit=il.cbegin();
而((ui
p、 很抱歉我的英语不好。std::array的问题是它必须是聚合类型,因此它没有构造函数 因此,只能进行聚合初始化或简单复制。
std::initializer\u list
不是std::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>());
}
模板
std::数组生成\数组执行(
std::初始值设定项\u列表t,
std::索引(U序列)
{
返回std::数组{*(t.begin()+Ns);
}
模板
std::数组生成数组(std::初始值设定项列表t){
如果(N>t.size())
把性病:扔出你的射程(“太疯狂了!”);
返回make_array_impl(t,std::make_index_sequence());
}
如果您愿意接受更多的变通方法,那么可以将其放入一个类中,以便在传递带括号的init列表的情况下捕获静态已知的长度冲突。但请注意,大多数阅读此代码的人都会坐在办公桌前
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
}
模板
结构阵列初始化器{
模板结构id{using type=U;};
std::数组t;
模板
ArrayInitializer(类型名称id::类型z)
:ArrayInitializer(z,std::make_index_sequence())
{
如果(N>z.size())
把性病:扔出你的射程(“太疯狂了!”);
}
模板
阵列初始化器(U&&…U)
:t{std::forward(u)…}
{ }
私人:
模板
阵列初始化器(标准::初始化器\u列表和t,
std::索引(U序列)
:t{*(t.begin()+Ns)…}
{ }
};
模板
std::阵列f(阵列初始化器ai){
返回标准::移动(ai.t);
}
int main(){
f({1,2,3,4,5});//好的
f({1,2,3,4,5,6});//“数组的初始值设定项太多”
std::初始值设定项列表il{1,2,3,4,5};
f(il);//好的
}
请注意,答案顶部的非静态案例和“head desk”案例都只检查您是否为
初始值设定项列表提供了太少的初始化元素,然后出错。如果您为初始值设定项列表
案例提供了太多,则后面的元素将被忽略。重新命名。。“dupped”是关于使用{..}
初始化成员数组的一般问题。这一个要求使用std::initializer\u列表来初始化std::
类型(不允许更改!)。他们的问题大不相同。@Alex你不能用复制来自算法()的吗?糟糕的英语?你写得比我的大多数同事都好。在堆栈溢出答案或问题中不需要这样的注释。社区将编辑任何不可理解的内容。@AndonM.Coleman-谢谢;我会尽量忽略我的语言不安全感。谢谢!是的,这两个示例都是可用的:@chris:Sorry,不是POD,而是聚合类型。见和。刚刚修改了文本
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>());
}
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
}