2016-06-10 63 views
6

例如如何實現方便的初始化?

#include <array> 

class Range 
{ 
public: 
    Range(std::array<float, 2> ends) : m_ends(ends) {} 

private: 
    std::array<float, 2> m_ends;  
}; 

,我可以

Range r({1, 2}); 

現在我有另一個類

class Box 
{ 
public: 
    Box(std::array<Range, 3> ranges) : m_ranges(ranges) {} 

private: 
    std::array<Range, 3> m_ranges;  
}; 

,我希望我可以做以下

Box b({{1,2}, {3,4}, {5,6}}); 

但我不能。我如何更改代碼才能實現。

+2

這工作:'盒子B {{{{{1,2}},{{3,4}}, {{5,6}}}}}'。 – user1887915

回答

4

std::array是有點怪。它沒有用戶定義的構造函數,所以它很像一個普通的結構體。所以std::array<float,2>很像

struct two_floats { 
    float array[2]; 
}; 

正因爲如此,如果你初始化一個,你會在邏輯上做這樣的:

two_floats   x = {{1,2}}; 
std::array<float,2> y = {{1,2}}; 

外括號是對結構本身和內部括號爲結構的內容。

它發生在工作,只提供一組括號:

two_floats x = {1,2}; 

但是,這是由於在C++中一個特殊的規則,允許括號在某些情況下可以省略。類似於您如何初始化一個二維數組,只有一組括號:

float x[2][2] = {1,2,3,4}; 

這就是當你初始化你這樣的範圍內所發生的事情:

Range r({1, 2}); 

即相當於

std::array<float,2> arg = {1,2}; // one set of braces omittted 
Range r(arg); 

但是這將更加明確地寫爲:

std::array<float,2> arg = {{1,2}}; 
Range r(arg); 
初始化框時

類似的事情發生。如果我們明確地寫出來的初始化它應該是這樣的:

std::array<float,2> box_arg1 = {{1,2}}; 
std::array<float,2> box_arg2 = {{3,4}}; 
std::array<float,2> box_arg3 = {{5,6}}; 
std::array<Range,3> box_args = {{box_arg1,box_arg2,box_arg3}}; 
Box b(box_args); 

因此,如果我們代替初始化,我們得到:

Box b({{{{1,2}},{{3,4}},{{5,6}}}}); 

和工程。但它很醜陋。這個初始化過於複雜,不允許在這裏省略額外的大括號,這是您遇到的問題。

的一種方法來解決此提供一種採取單獨的數組元素的附加構造。

class Range 
{ 
public: 
    Range(float x,float y) : m_ends{x,y} { } 
    Range(std::array<float, 2> ends) : m_ends(ends) {} 

private: 
    std::array<float, 2> m_ends; 
}; 

class Box 
{ 
public: 
    Box(Range x,Range y,Range z) : m_ranges{x,y,z} {} 
    Box(std::array<Range, 3> ranges) : m_ranges(ranges) {} 

private: 
    std::array<Range, 3> m_ranges; 
}; 

,現在您可以初始化你的盒子就像你本來想:

Box b({{1,2}, {3,4}, {5,6}}); 
0

AFAIK它不能與陣列來完成,你不得不求助於基本類型

struct Range 
{ 
    float m_ends[2] ;  
}; 


Range r = {1.0f, 2.0f}; 


struct Box 
{ 
    Range m_ranges[3];  
}; 


Box b = {{{1.0f, 2.0f}, {1.0f, 2.0f}, {1.0f, 2.0f}}}; 
1

問題

此代碼:Box b({{1,2}, {3,4}, {5,6}});正在努力的Range即使Rangeaggregate initialize情況下不是骨料。

集合初始化爲list-初始化的一種形式,其 初始化聚集

聚集是以下類型之一:

陣列型

類型(典型地,結構或聯盟),它有

否 私有或受保護的非靜態數據成員

沒有用戶提供的構造,包括那些來自公共基地 (sinceC++ 17)(顯式默認或刪除構造允許)

繼承(因爲C++ 11)沒有虛擬的,私人的,或受保護的(因爲C++ 17)基 類

沒有虛成員函數

調用的Range構造explicitcly只有總初始化std::array

Box b({Range({1,2}), Range({3,4}), Range({5,6})}); 
+1

它不是聚合初始化,它試圖使用[list initialize](http://en.cppreference.com/w/cpp/language/list_initialization) – user1887915

3

我剛落陣列和使用通常的領域。如果您真的需要,可以隨時添加一個operator[]重載。只要將字段名稱更改爲您實際建模的內容即可。

class Range 
{ 
public: 
    Range(float x, float y) : m_x{x}, m_y{y} 
    {} 
private: 
    float m_x, m_y; 
}; 

class Box 
{ 
public: 
    Box(Range w, Range h, Range d) : m_w{w}, m_h{h}, m_d{d} 
    {} 
private: 
    Range m_w, m_h, m_d; 
}; 

Live Demo

+0

'operator []'將需要一個'if'判斷,它會影響性能嗎? –

1

也許你可以使用初始化列表:

class Range 
{ 
public: 
    Range(std::initializer_list<float> ends) : m_ends(ends) {} 
    float a() { 
    return m_ends[0]; 
    } 
    float b() { 
    return m_ends[1]; 
    } 

private: 
    std::vector<float> m_ends; 
}; 

class Box 
{ 
public: 
    Box(std::initializer_list<Range> ranges) : m_ranges(ranges) {} 

    void print() 
    { 
    for (auto& i : m_ranges) 
    { 
     std::cout << i.a() << "," << i.b() << std::endl; 
    } 
    } 

private: 
    std::vector<Range> m_ranges; 
}; 


    Range r({ 1,2 }); 
    Box b({ {1,2},{3,4},{5,6} }); 
    b.print(); 

1,2 
3,4 
5,6 
+0

你不管理大小。 – Jarod42

+1

@ Jarod42這是真的,只是顯示一條路徑 –

0

爲了得到正確的初始化列表中,首先列出它的完整形式:

Box b{ 
    array<Range, 3>{{ // std::array needs aggregate-initialize, 
         // and have to initialize a inner array 
         // without a addition '{', C++ is unable to 
         // know that the inner element is Range 
     Range{ 
      {1, 2} // short-hand for array<float>{{3, 4}} 
     }, 
     Range{ 
      {3, 4} 
     }, 
     Range{ 
      {5, 6} 
     } 
    }} 
} 

刪除所有類型除了Box,我們得到:

Box b{ {{ {{1, 2}}, {{3, 4}}, {{5, 6}} }} }