2016-08-13 3 views
11

中括弧で囲まれたイニシャライザの代わりにstd::initializer_listオブジェクトを使用して配列を初期化できますか? http://en.cppreference.com/w/cpp/language/aggregate_initialization中括弧で囲まれたイニシャライザの代わりにstd :: initializer_listを使って配列を初期化できますか?

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;を使用することができます配列を初期化しますか?

+5

Repoened .. "duped"はメンバー配列の初期化に関する一般的な質問でした。これは、 'std :: initializer_lists'を使って' std :: '型を初期化することを要求します(変更は許可されていません!)。彼らは大きく異なる質問です。 –

+0

@Alex 'algorithm'([example](https://godbolt.org/g/cKiBNg))から' copy'を使用できませんか? – skypjack

答えて

8

その他の回答は正しくありません。しかし、少しのヘルパーで、あなたはより多くの回避策に開かれている場合は、あなたがブレースのinitリストを渡す場合のために、静的に既知の長さ違反をキャッチするために、クラスにこれを置くことができる

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 
} 

注解答と「頭デスク」ケースの上部の非静的ケースの両方が唯一のあなたも提供するかどうかをチェックしますかという警告が表示されいくつかの初期化要素、およびエラーは、の場合は、 initializer_listの大文字小文字をあまりにも多く指定すると、末尾の要素は無視されます。

+0

ありがとうございました!はい、どちらの例も使用できます:http://ideone.com/s0ciUWとhttp://ideone.com/fbnM6W – Alex

6

私が知る限り、いいえ:std::arraystd::initializer_listで初期化することはできません。

std::arrayは、古典的なCスタイルの配列の軽量の置き換え(ラッパー)を意図しています。ライトはコンストラクタなしであるため、暗黙のコンストラクタのみを使用できます。

Cスタイルの配列で可能なので、暗黙のコンストラクタによる集約の初期化による構築が可能です。

しかし、std::initializer_listはクラスであり、集約初期化より複雑です。

あなたは、一例で、std::initializer_liststd::vectorを初期化することができますがstd::initializer_listを受けるstd::vectorための明示的なコンストラクタは、そこにあるだけの理由。しかし、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++; 

p.s .:私の悪い英語のために申し訳ありません。

+6

_Bad English?_あなたは私の同僚のほとんどよりも優れています。 Stack overflowの回答や質問には、そのようなコメントは必要ありません。コミュニティーは理解できないものを編集します。 –

+1

@ AndonM.Coleman - ありがとうございます。私は言語の不安を無視しようとします。 – max66

2

std::arrayの問題は、集計タイプである必要があります。したがって、コンストラクタはありません。

したがって、集約の初期化または簡単なコピーのみが可能です。 std::initializer_liststd::array以外のクラスなので、暗黙の変換が必要です(欠落している)。

参考として、http://en.cppreference.com/w/cpp/language/aggregate_initialization およびhttp://en.cppreference.com/w/cpp/container/arrayを参照してください。

+0

[PODの特定の要件はこれを禁止していますか?](http://coliru.stacked-crooked.com/a/d332ff1ce89c8817) – chris

+0

@chris:申し訳ありません。* POD *ではなく、*集計*タイプです。 http://en.cppreference.com/w/cpp/language/aggregate_initializationおよび http://en.cppreference.com/w/cpp/container/arrayを参照してください。 テキストを固定しました –

関連する問題