2011-08-01 55 views
24

可能重複:
How do I initialize a member array with an initializer_list?如何構造具有初始化列表的std :: array對象?

您可以構建一個std ::陣列就好用初始化列表:

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

然而,當我試圖建立它從std::initializer_list作爲數據成員或類中的基礎對象,它不起作用:

#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'}; 

錯誤用gcc 4.6:

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>&&' 

我怎樣才能得到它的工作,使我的包裝類可以用一個初始化列表來初始化,這樣:

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

回答

26

std::array<>沒有構造函數接受一個std::initializer_list<>(初始化列表構造器),有什麼可能意味着一個std::initializer_list<>傳遞給類的構造函數,使得可工作沒有特別的語言支持。所以那失敗了。

對於它的工作,你的派生類需要捕獲的所有元素,然後轉發它們,構造模板:

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

請注意,您在這種情況下,需要{{...}}因爲撐省音(省略像括號你案件)在那個地方不起作用。它只允許在T t = { ... }的形式的聲明中。因爲std::array<>由嵌入原始數組的結構組成,所以需要兩級大括號。不幸的是,我相信std::array<>的確切聚合結構是未指定的,因此您需要希望它能在大多數實現中起作用。

+4

Clang抱怨輸入應該是'E && ... e'。 (有時候,g ++會告訴我要殺人。) –

+1

難道不會覆蓋副本構造函數嗎?有可能限制它更多?,如'模板(std :: declval ()...)...}}> enum_addressable_array(E && ... e):base_t {{std :: forward (e)...}} {}(我無法使它工作) – alfC

+1

@alfC模板永遠不會比隱式生成的特殊成員函數更好的匹配,因爲它們是完全匹配的(即使它們是隱含的或顯式聲明爲已刪除),但棘手的部分是,如果你傳遞類似'enum_addressable_array&'。 –

10

std::array沒有一個構造函數,它需要一個std::initializer_list。這是一件好事,因爲初始化器列表可以大於數組的固定大小。

可以通過測試該初始化列表不小於陣列的尺寸大,然後用std::copy複製初始化列表的元素的std::arrayelems構件初始化。

23

由於std::array是包含聚合結構(這是一個非集合本身,並沒有一個構造函數一個std::initializer_list),你可以使用雙用初始化列表初始化結構中的底層骨料-braces語法像這樣:

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

注意...這是簡單地使用C++初始化列表初始化的std::array公開訪問數組成員,這是不使用std::initializer_list

相關問題