2013-04-13 46 views
2

我知道我可以通過使用數組來存儲Matrix的數據。是否可以將統一的初始化和構造函數結合起來?

Matrix<2, 2> m = { 1, 2 
        3, 4 }; 

但我想做到這一點,使用矢量來代替,如使用數組是很糟糕的時候矩陣變大,你跑出來的堆棧空間

Matrix m(2, 2) = { 1, 2 
        3, 4 }; 

可以這樣(或東西相似)做?

+0

當然,你可以寫一個接受'std :: initializer_list '的構造函數。 –

+0

@KerrekSB:你確定嗎? AFAICT這是不可能的([live example](http://liveworkspace.org/code/3kW04t$309)) –

+0

你對這種語法感興趣嗎?或者稍微不同的調用可以嗎? – delnan

回答

2

如果您在編譯時有固定的大小,但想要使用動態分配,您可以分別選擇每個對象的分配類型(「堆棧」/「堆」)或將動態分配構建到Matrix類。

Matrix類以外的動態分配的示例。請注意,使用初始化列表可防止在編譯時檢查傳遞給ctor的元素數量(除了聲明contexprMatrix的實例)。因此,我介紹了一個相當愚蠢的補充來演示編譯時大小檢查。

#include <memory> 
#include <iostream> 
#include <array> 

template < typename T, std::size_t rows, std::size_t columns > 
struct Matrix 
{ 
public: 
    Matrix(std::initializer_list<T> p) 
    { 
     if(p.size() != rows*columns) { /* throw */ } 

     std::copy(p.begin(), p.end(), storage_member.begin()); 
    } 
    Matrix(std::array<T, columns*rows> const& p) 
    { 
     std::copy(p.begin(), p.end(), storage_member.begin()); 
    } 

    Matrix(std::initializer_list< std::initializer_list<T> > p) 
    { 
     if(p.size() != rows) { /* throw */ } 

     auto itRow = p.begin(); 
     for(std::size_t row = 0; row < rows; ++row, ++itRow) 
     { 
      if(itRow->size() != columns) { /* throw */ } 

      auto itCol = itRow->begin(); 
      for(std::size_t col = 0; col < columns; ++col, ++itCol) 
      { 
      storage_member[col+row*columns] = *itCol; 
      } 
     } 
    } 
    Matrix(std::array<std::array<T, columns>, rows> const& p) 
    { 
     for(std::size_t row = 0; row < rows; ++row) 
     { 
      for(std::size_t col = 0; col < columns; ++col) 
      { 
      storage_member[col+row*columns] = p[row][col]; 
      } 
     } 
    } 

    // getters, setters 
    T& operator() (std::size_t row, std::size_t col) 
    { 
     return storage_member[col+row*columns]; 
    } 
private: 
    // storage, e.g. 
    std::array<T, columns*rows> storage_member; 
}; 

template < typename T, typename... TP> 
constexpr std::array<T,sizeof...(TP)+1> m(T&& p, TP... pp) 
{ 
    return {{p, pp...}}; 
} 

// usage: 
int main() 
{ 
    using My_Matrix_Type = Matrix < int, 2, 2 >; 

    std::unique_ptr <My_Matrix_Type> pmyMatrix0{ new My_Matrix_Type({1,2,3,4}) }; 
    std::unique_ptr <My_Matrix_Type> pmyMatrix1{ new My_Matrix_Type({{1,2},{3,4}}) }; 

    // with compile-time size checks 
    std::unique_ptr <My_Matrix_Type> pmyMatrix2{ new My_Matrix_Type(m(1,2,3,4)) }; 
    std::unique_ptr <My_Matrix_Type> pmyMatrix3{ new My_Matrix_Type(m(m(1,2), m(3,4))) }; 
    // a more fancy but possible syntax, would require some additional effort: 
    //std::unique_ptr <My_Matrix_Type> pmyMatrix4{ new My_Matrix_Type(b(1,2)(3,4)) }; 


    std::cout << (*pmyMatrix0)(1,1) << std::endl; 
    std::cout << (*pmyMatrix1)(1,1) << std::endl; 
    std::cout << (*pmyMatrix2)(1,1) << std::endl; 
    std::cout << (*pmyMatrix3)(1,1) << std::endl; 
} 

在上面的例子中,你可以立刻被動態分配的數組替換storage_member使動態分配內置。


如果你不知道在編譯時的大小,你必須建立動態分配到Matrix類(如上所述)。正如你可以推導出2級初始化列表的大小(列,行),你只需要移除採用固定大小數組的ctors並更改1級初始化列表,例如:

template < typename T > // no size parameters! 
struct Matrix 
{ 
    Matrix(std::size_t columns, std::size_t rows, std::initializer_list<T> p); 
    Matrix(std::initializer_list< std::initializer_list<T> > p); 
    // maybe an additional ctor for dynamically allocated arrays 

    // getters, setters, data members 
}; 

// usage: 
Matrix myMatrix0(2, 2, {1,2,3,4}); 
Matrix myMatrix1({{1,2},{3,4}}); 
+0

如果有人知道如何使用'make_unique'工作(尤其是帶有初始化列表的例子),我會很感激評論/編輯。 – dyp

相關問題