简体   繁体   English

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

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

Can I initialize an array using the std::initializer_list object instead of brace-enclosed initializer?我可以使用std::initializer_list对象而不是大括号封闭的初始化程序来初始化数组吗?

As known, we can do this: http://en.cppreference.com/w/cpp/language/aggregate_initialization众所周知,我们可以这样做: 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};

But I can't initialize an array by std::initializer_list il;但是我不能通过std::initializer_list il;初始化一个数组std::initializer_list il; :

http://ideone.com/f6aflX 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;
}

But how can I use std::initializer_list il;但是我怎样才能使用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.如果您愿意接受更多变通方法,则可以将其放入一个类中,以在传递带括号的 init 列表的情况下捕获静态已知的长度违规。 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
}

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.请注意,答案顶部的非静态情况和“head-desk”情况都只检查您是否提供了太少的初始化元素,然后为initializer_list情况检查错误。 If you provide too many for the initializer_list case, the trailing elements are just ignored.如果为initializer_list情况提供太多,则只会忽略尾随元素。

As far I know, no: you can't initialize a std::array with a std::initializer_list .据我所知,没有:你不能初始化std::arraystd::initializer_list

The problem is that std::array is intended as a lightweight replacement (a wrapper) for the classic C-style array.问题在于std::array旨在作为经典 C 样式数组的轻量级替代品(包装器)。 So light that is without constructors, so only implicit constructor can be used.如此轻巧,没有构造函数,因此只能使用隐式构造函数。

The construction with aggregate initialization (via implicit constructor) is possible because it's possible for the C-style array.具有聚合初始化(通过隐式构造函数)的构造是可能的,因为它可以用于 C 样式数组。

But std::initializer_list is a class, more complicated than an aggregate inizialization.但是std::initializer_list是一个类,比聚合std::initializer_list更复杂。

You can initialize, by example, a std::vector with a std::initializer_list but only because there is an explicit constructor, for std::vector , that receive a std::initializer_list .例如,您可以使用std::initializer_list std::vector ,但这仅仅是因为std::vector有一个显式构造函数,它接收std::initializer_list But std::vector is a heavier class.但是std::vector是一个更重的类。

The only solution that I see is a 2 step way: (1) construction and (2) copy of the std::initializer_list values.我看到的唯一解决方案是 2 步方法:(1) 构造和 (2) std::initializer_list值的副本。 Something like就像是

std::array<int, 3> arr5;

auto  ui = 0U;
auto  cit = il.cbegin();

while ( (ui < arr5.size()) && (cit != il.cend()) )
   arr5[ui++] = *cit++;

ps: sorry for my bad English. ps:抱歉我的英语不好。

The problem with std::array is that it is required to be an aggregate type, hence it does not have constructors. std::array的问题在于它必须是聚合类型,因此它没有构造函数。

Hence only aggregate initialization or trivial copy are possible.因此,只有聚合初始化或平凡复制是可能的。 std::initializer_list is a class other than std::array , so a (missing) implicit conversion is required. std::initializer_liststd::array以外的类,因此需要(缺少)隐式转换。

See http://en.cppreference.com/w/cpp/language/aggregate_initialization and http://en.cppreference.com/w/cpp/container/array for reference.请参阅http://en.cppreference.com/w/cpp/language/aggregate_initializationhttp://en.cppreference.com/w/cpp/container/array以供参考。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 std :: initializer_list无法从中推断出来<brace-enclosed initializer list> - std::initializer_list not able to be deduced from <brace-enclosed initializer list> 用大括号括起来的初始化程序列表 - brace-enclosed initializer list 无法从大括号括起来的初始化列表转换为std元组 - Could not convert from brace-enclosed initializer list to std tuple std::forward 无法转换大括号括起来的初始化列表 - std::forward cannot convert brace-enclosed initializer list 无法从大括号括起来的初始化列表转换为std :: vector - Could not convert from brace-enclosed initializer list to std::vector 数组大小可变的模板类:使用数组引用或括号括起来的初始化程序列表进行初始化 - Template class with variable array size: initialize with array reference or brace-enclosed initializer list 数组初始化需要用大括号括起来的初始化器列表lambda - array initialization requires a brace-enclosed initializer list lambda 无法从转换 <brace-enclosed initializer list> 到int(*)数组 - Could not convert from <brace-enclosed initializer list> to int(*) array QtConcurrent错误:数组初始化需要大括号括起来的初始化器列表 - QtConcurrent Error: Array Initialization Requires a brace-enclosed Initializer list 数组初始化需要用大括号括起来的初始化器列表 - array initialization requires a brace-enclosed initializer list
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM