2013-05-02 264 views
9

我有一個struct持有一個數組,我想傳遞一個初始化列表到結構的構造函數被轉發到數組。爲了說明這一點,我想:用初始值設定項列表初始化成員數組的正確方法是什麼?

#include <initializer_list> 

struct Vector 
{ 
    float v[3]; 

    Vector(std::initializer_list<float> values) : v{values} {} 
}; 

int main() 
{ 
    Vector v = {1, 2, 3}; 
} 

Which resulted in the error

error: cannot convert ‘std::initializer_list<float>’ to ‘float’ in initialization

I tried using parentheses instead of bracesv但給了錯誤:

error: incompatible types in assignment of ‘std::initializer_list<float>’ to ‘float [3]’

我對試圖做到這一點的主要動機是爲了避免下面警告叮噹:

template <int N> 
struct Vector 
{ 
    float v[N]; 
}; 

template <> 
struct Vector<2> 
{ 
    float x, y; 
}; 

int main() 
{ 
    Vector<2> v2 = {1.0f, 2.0f};   // Yay, works 
    Vector<3> v3 = {1.0f, 2.0f, 3.0f}; // Results in warning in clang++ 
    Vector<3> u3 = {{1.0f, 2.0f, 3.0f}}; // Must use two braces to avoid warning 
    // If I could make Vector<N> take an initializer list in its constructor, I 
    // could forward that on to the member array and avoid using the double braces 
} 

warning: suggest braces around initialization of subobject

所以我的問題是:我怎樣才能初始化一個成員數組與初始化列表? (即我怎樣才能使第一個代碼工作?或者是不可能的?

+0

對於一個聚合,你甚至不需要ctor。請注意'initializer_list'的大小是可變的。 initializer-list初始化和_list-initialization_(這是一種語言結構,並可能導致使用初始化器列表調用ctor)之間也有區別。 – dyp 2013-05-02 14:54:29

+0

你真的不能這樣做,但是你可以使用'std :: array'嗎? – juanchopanza 2013-05-02 14:54:52

+0

他可以使用std :: array,但是我把它看作是關於語言的問題,而不是標準庫。而且,在適當尊重任何人的情況下,告訴某人去讀標準圖書館就像告訴幼兒通過閱讀莎士比亞來學習英語一樣。所以std :: array不是一個很好的答案。 – 2016-03-02 00:32:35

回答

9

如果你的類是aggregate,你可以用你的語法

template < std::size_t len > 
struct Vector 
{ 
    float elems[len]; 
}; 

Vector<3> v = {1.0f, 2.0f, 3.0f}; 

注意:這是可能的,因爲大括號省略。不需要v = {{1,2,3}};,儘管這也是可能的.Clang發出這個警告,因爲更清晰和較少容易出錯的語法是用雙括號(一個用於初始化v和一個用於初始化子集合elems)。

如果你的類不是彙總,您可以使用可變參數模板:

#include <array> 
#include <cstddef> 

template < std::size_t len > 
struct Vector 
{ 
    std::array < float, len > m; // also works with raw array `float m[len];` 

    template < typename... TT > 
    Vector(TT... pp) : m{{pp...}} 
    {} 

    // better, using perfect forwarding: 
    // template < typename... TT > 
    // Vector(TT&&... pp) : m{{std::forward<TT>(pp)...}} 
    // {} 
}; 

Vector<3> a = {1.0f, 2.0f, 3.0f}; 
2

嘗試使用std::copy

Vector(std::initializer_list<float> values) 
{ 
    std::copy(values.begin(), values.end(), v); 
} 
+0

如果列表大於v的容量,該怎麼辦? – 2016-03-02 00:25:52

12

純C風格的數組是不可轉讓。如果切換到使用std::array,則初始化變得很簡單。

#include <array> 

struct Vector 
{ 
    std::array<float, 3> v; 

    Vector(std::array<float, 3> const& values) 
    : v(values) 
    {} 
}; 

int main() 
{ 
    Vector v{{1, 2, 3}}; 
} 
+0

+1推薦'std :: array'。它允許更好的初始化語法。 – 2013-05-02 15:05:25

0

初始化數組非靜態成員,使用聚合語法。也就是說,直接使用N元素填充支撐列表,其中N是數組中元素的數量。如果元素類型爲Default-Constructible,則可以使用少於N;缺失的元素將被初始化。

std::initializer_list到數組沒有轉換。即使您使用的是可以轉換爲數組引用的源類型(從不是值),也不能利用成員初始化程序中的轉換,因爲數組不是可分配的。在這些情況下,你必須在構造函數體內使用類似std::copy的東西。

注意多維數組,因爲數組不是可指定的,所以只能使用支撐列表來表示子數組。也有選擇大括號的方法;使用一個std::remove_all_extents<TheArrayType>::type項目的扁平列表並且編譯器將make-do。 (當內部非數組類型是內置字符類型時,有時可以使用帶引號的字符串作爲多維數組的下一個內部初始化程序。)

相關問題