我可以使用std :: initializer_list而不是括号括起来的初始化程序来初始化数组吗? [英] Can I initialize an array using the std::initializer_list instead of brace-enclosed initializer?

查看:133
本文介绍了我可以使用std :: initializer_list而不是括号括起来的初始化程序来初始化数组吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以使用 std :: initializer_list 对象而不是括号括起来的初始化程序来初始化数组吗?

Can I initialize an array using the std::initializer_list object instead of brace-enclosed initializer?

众所周知,我们可以这样做: http://en.cppreference.com/w/cpp/language/aggregate_initialization

As known, we can do this: http://en.cppreference.com/w/cpp/language/aggregate_initialization

unsigned char b[5]{"abc"};
// equivalent to unsigned char b[5] = {'a', 'b', 'c', '\0', '\0'};

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初始化数组;

http://ideone.com/f6aflX

#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 ; 初始化数组?

But how can I use std::initializer_list il; to initialize an array?

推荐答案

其他正确回答的问题是,这不可能预先解决。但是如果没有小帮手,您就可以很接近

Other answered correctly said this is not possible upfront. But with little helpers, you can get pretty close

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>());
}

如果您愿意接受更多的解决方法,可以将其放在一个类中可以在传递括号初始化列表的情况下捕获静态已知的长度违规。但请注意,大多数阅读此代码的人都会在前台

If you are open to more work arounds, you can put this into a class to catch statically-known length violations for the cases where you pass a braced init list. But be warned that most people who read this code will 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
}

请注意,答案和总部情况仅检查 initializer_list 情况下是否提供了太多的初始化元素,然后出错。如果您为 initializer_list 案例提供了太多内容,则尾随元素将被忽略。

Note that both the non-static case at the top of the answer and the "head-desk" case do only check whether you provide too few initializing elements, and errors out then, for the initializer_list case. If you provide too many for the initializer_list case, the trailing elements are just ignored.

这篇关于我可以使用std :: initializer_list而不是括号括起来的初始化程序来初始化数组吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆