2011-08-01 21 views
24

Olası Çoğalt: Bir başlatıcı listesi ile gayet bir std :: dizi oluşturabilirsiniz
How do I initialize a member array with an initializer_list?Std :: array nesnesi, başlatıcı listesiyle nasıl oluşturulur?

: Ancak

std::array<int, 3> a = {1, 2, 3}; // works fine 

, bunu inşa etmek deneyin std::initializer_list'dan bir sınıftaki bir veri üyesi veya temel nesne olarak, işe yaramıyor:

gcc 4.6 ile
#include <array> 
#include <initializer_list> 

template <typename T, std::size_t size, typename EnumT> 
struct enum_addressable_array : public std::array<T, size> 
{ 
    typedef std::array<T, size> base_t; 
    typedef typename base_t::reference reference; 
    typedef typename base_t::const_reference const_reference; 
    typedef typename base_t::size_type size_type; 

    enum_addressable_array(std::initializer_list<T> il) : base_t{il} {} 

    reference operator[](EnumT n) 
    { 
     return base_t::operator[](static_cast<size_type>(n)); 
    } 

    const_reference operator[](EnumT n) const 
    { 
     return base_t::operator[](static_cast<size_type>(n)); 
    } 
}; 

enum class E {a, b, c}; 
enum_addressable_array<char, 3, E> ea = {'a', 'b', 'c'}; 

hatalar:

test.cpp: In constructor 'enum_addressable_array<T, size, EnumT>::enum_addressable_array(std::initializer_list<T>) [with T = char, unsigned int size = 3u, EnumT = E]': 
test.cpp:26:55: instantiated from here 
test.cpp:12:68: error: no matching function for call to 'std::array<char, 3u>::array(<brace-enclosed initializer list>)' 
test.cpp:12:68: note: candidates are: 
include/c++/4.6.1/array:60:12: note: std::array<char, 3u>::array() 
include/c++/4.6.1/array:60:12: note: candidate expects 0 arguments, 1 provided 
include/c++/4.6.1/array:60:12: note: constexpr std::array<char, 3u>::array(const std::array<char, 3u>&) 
include/c++/4.6.1/array:60:12: note: no known conversion for argument 1 from 'std::initializer_list<char>' to 'const std::array<char, 3u>&' 
include/c++/4.6.1/array:60:12: note: constexpr std::array<char, 3u>::array(std::array<char, 3u>&&) 
include/c++/4.6.1/array:60:12: note: no known conversion for argument 1 from 'std::initializer_list<char>' to 'std::array<char, 3u>&&' 

nasıl gibi, benim sarmalayıcı sınıf bir başlatıcı-listeyle başlatıldı böylece çalışmak için alabilirsiniz:

enum_addressable_array<char, 3, E> ea = {'a', 'b', 'c'}; 

cevap

26

bir std::initializer_list<> (başlatıcı liste yapıcısı) alır ve bu işe öyle ki bir sınıf yapıcıları için std::initializer_list<> geçmek ne anlama geldiğini için özel dil desteği vardır hiçbir yapıcı vardır. Yani bu başarısız olur. o çalışması için

, sizin türetilmiş sınıf bunları iletmek sonra tüm unsurları yakalamak ve ihtiyacı, bir yapıcı şablonu:

template<typename ...E> 
enum_addressable_array(E&&...e) : base_t{{std::forward<E>(e)...}} {} 

Not ayracı elision (gibi parantez atlayarak çünkü bu durumda {{...}} ihtiyacınızı dava) o yerde çalışmıyor. Sadece T t = { ... } formundaki beyanlarda izin verilir. Bir std::array<>, bir ham diziyi içine alan bir yapıdan oluştuğundan, bu iki seviyede parantez gerektirir. Ne yazık ki, std::array<>'un kesin toplam yapısının belirtilmemiş olduğuna inanıyorum, bu yüzden çoğu uygulamada çalışmasını umuyor olmalısınız.

+4

Clang, girdinin "E && ... e" olması gerektiğini düşünüyor. (Ve bazen, g ++ insanları öldürmem gerektiğini söyler.) –

+1

Bu kopyalayıcı ve bunun üzerine yazılmasın mı? Daha fazla kısıtlamak mümkün mü?, 'Template (std :: declval () ...) ...}}> enum_addressable_array (E && ... e): temel_t {{std :: ileri (e) ...}} {} '(İşe yaramayacağım) – alfC

+1

@alfC Bir şablon, örtük olarak oluşturulmuş özel üye işlevlerinden daha iyi bir eşleşme olmayacaktır. ya da açıkça silinmiş olarak ilan edilir. Ancak, zor bir bölüm, enum_addressable_array & '. –

10

Bir std::array, std::initializer_list numaralı bir kurucuya sahip değildir. Bu iyi bir şeydir çünkü başlatıcı listeleri dizinin sabit boyutundan daha büyük olabilir.

Sen başlatıcı listesi dizinin boyutundan büyük olmadığını test ve sonra std::copy ile std::array ait elems üyesine başlatıcı listenin elemanlarını kopyalayarak bunu başlatabilir. Bir std::array yana

23

, bir çift kullanarak bir başlatıcı listesi ile yapı içinde yatan agrega başlatabilir (Bir toplama kendisi değildir ve bir std::initializer_list alan yapıcıya sahip değildir) bir agrega içeren bir yapıdır -braces sözdizimi şöyle: Bu basitçe std::array herkese açık dizisi üye başlatmak için bir C++ başlatıcı listesini kullanıyor ... Bu std::initializer_list kullanmadığını

std::array<int, 4> my_array = {{1, 2, 3, 4}}; 

not. Bir std::array<>

İlgili konular