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
}