簡體   English   中英

我可以使用 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', '\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;初始化一個數組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; 初始化一個數組?

其他回答正確的人說這是不可能的。 但是有小幫手,你可以非常接近

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

如果您願意接受更多變通方法,則可以將其放入一個類中,以在傳遞帶括號的 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
}

請注意,答案頂部的非靜態情況和“head-desk”情況都只檢查您是否提供了太少的初始化元素,然后為initializer_list情況檢查錯誤。 如果為initializer_list情況提供太多,則只會忽略尾隨元素。

據我所知,沒有:你不能初始化std::arraystd::initializer_list

問題在於std::array旨在作為經典 C 樣式數組的輕量級替代品(包裝器)。 如此輕巧,沒有構造函數,因此只能使用隱式構造函數。

具有聚合初始化(通過隱式構造函數)的構造是可能的,因為它可以用於 C 樣式數組。

但是std::initializer_list是一個類,比聚合std::initializer_list更復雜。

例如,您可以使用std::initializer_list std::vector ,但這僅僅是因為std::vector有一個顯式構造函數,它接收std::initializer_list 但是std::vector是一個更重的類。

我看到的唯一解決方案是 2 步方法:(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++;

ps:抱歉我的英語不好。

std::array的問題在於它必須是聚合類型,因此它沒有構造函數。

因此,只有聚合初始化或平凡復制是可能的。 std::initializer_liststd::array以外的類,因此需要(缺少)隱式轉換。

請參閱http://en.cppreference.com/w/cpp/language/aggregate_initializationhttp://en.cppreference.com/w/cpp/container/array以供參考。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM