2011-10-07 4 views
16

câu hỏi ngắn: Có cách nào ngắn hơn để làm điều nàycách ít verbose tuyên bố std :: đa chiều mảng

array<array<atomic<int>,n>,m> matrix; 

Tôi đã hy vọng cho một cái gì đó giống như

array< atomic< int>,n,m> matrix;  

nhưng nó không làm việc. ..

+0

Điều gì không hiệu quả? Thông báo lỗi là gì?Điều đó sẽ giúp ai đó thực sự trả lời câu hỏi. Tôi hiểu các lỗi mẫu là chính họ tiết, nhưng ít nhất một số sẽ giúp ích. – Mahesh

+0

Vâng nó thiếu một '>' cho người mới bắt đầu. – Mat

+0

mảng kiểm tra; sai số đối số mẫu (3, nên là 2) – NoSenseEtAl

Trả lời

11

Khi lồng nhau, tiêu chuẩn :: mảng có thể trở nên rất khó đọc và không cần thiết tiết. Thứ tự ngược lại của các kích thước có thể đặc biệt khó hiểu.

Ví dụ:

std::array < std::array <int, 3 > , 5 > arr1; 

so với

char c_arr [5][3]; 

Ngoài ra, lưu ý rằng bắt đầu(), kết thúc() và kích thước() tất cả trở về giá trị vô nghĩa khi bạn tổ std :: mảng.

Vì những lý do này tôi đã tạo các vùng chứa đa chiều có kích thước cố định của riêng mình, mảng_2d và mảng_3d. Họ có lợi thế là họ làm việc với C++ 98.

Chúng tương tự với std :: array nhưng đối với mảng đa chiều có kích thước 2 và 3. Chúng an toàn hơn và không có hiệu suất kém hơn so với các mảng đa chiều có sẵn. Tôi không bao gồm một vùng chứa cho các mảng đa chiều có kích thước lớn hơn 3 vì chúng không phổ biến. Trong C++ 11, phiên bản mẫu variadic có thể được tạo ra, hỗ trợ một số thứ tự tùy ý (ví dụ như ví dụ của Michael Price).

Một ví dụ về các biến thể hai chiều:

//Create an array 3 x 5 (Notice the extra pair of braces) 
fsma::array_2d <double, 3, 5> my2darr = {{ 
{ 32.19, 47.29, 31.99, 19.11, 11.19}, 
{ 11.29, 22.49, 33.47, 17.29, 5.01 }, 
{ 41.97, 22.09, 9.76, 22.55, 6.22 } 
}}; 

Full tài liệu có sẵn ở đây: http://fsma.googlecode.com/files/fsma.html

Bạn có thể tải thư viện ở đây: http://fsma.googlecode.com/files/fsma.zip

+0

u quy tắc, tôi đã tự hỏi tại sao họ didnt làm điều này trong std ::, có lẽ họ muốn giữ nó tinh khiết chung :) – NoSenseEtAl

+1

btw tại sao .size() vô nghĩa? Nó không hoạt động như mong đợi? arr.size() == dim1, arr [0] .size() = dim2 – NoSenseEtAl

+4

Có lẽ vô nghĩa là một từ quá mạnh. Ý tôi là nó không trả về tổng số phần tử trong mảng đa chiều. btw Tôi đồng ý rằng một cái gì đó như nó phải ở trong tiêu chuẩn. Sẽ thay thế tốt cho mảng đa chiều có sẵn không an toàn :) – Ricky65

31

Bí danh mẫu có thể trợ giúp:

#include <array> 

template <class T, unsigned I, unsigned J> 
using Matrix = std::array<std::array<T, J>, I>; 

int main() 
{ 
    Matrix<int, 3, 4> matrix; 
} 
+0

Thật không may, hiện tại không có trình biên dịch nào thực hiện tính năng này (ít nhất là tôi biết, tôi rất vui khi được chứng minh là sai) :( –

+1

rất đẹp, tôi sợ rằng MACRO đen ma thuật là cách duy nhất (để HELL): P – NoSenseEtAl

+3

Tôi thử nghiệm nó trên clang/OS X trước khi đăng bài –

32

Một cách giải quyết ngon miệng cho các trình biên dịch không hỗ trợ mẫu bí danh được nêu ra là sử dụng một metafunction đơn giản để tạo ra các loại:

#include <cstddef> 
#include <array> 

template<class T, std::size_t RowsN, std::size_t ColumnsN> 
struct Matrix 
{ 
    typedef std::array<std::array<T, ColumnsN>, RowsN> type; // row major 

private: 
    Matrix(); // prevent accidental construction of the metafunction itself 
}; 

int main() 
{ 
    Matrix<int, 3, 4>::type matrix; 
} 
12

Giải pháp sử dụng mẫu variadic (hơi phức tạp hơn so với mẫu bí danh, nhưng tổng quát hơn mục đích)

template <typename T, std::size_t thisSize, std::size_t ... otherSizes> 
class multi_array : private std::array<multi_array<T, otherSizes...>, thisSize> 
{ 
using base_array = std::array<multi_array<T, otherSizes...>, thisSize>; 

public: 
    using base_array::operator[]; 
    // TODO: add more using statements to make methods 
    // visible. This is less typing (and less error-prone) 
    // than forwarding to the base_array type. 
}; 

template <typename T, std::size_t thisSize> 
class multi_array<T, thisSize> : private std::array<T, thisSize> 
{ 
using base_array = std::array<T, thisSize>; 

public: 
    using base_array::operator[]; 
    // TODO: add more using statements to make methods 
    // visible. This is less typing (and less error-prone) 
    // than forwarding to the base_array type. 
}; 

Có thể có một số cải tiến về việc gán cho không phải là mảng của mảng có thể được thực hiện.

Tôi đã thử nghiệm với công trình xây dựng clang/LLVM tương đối gần đây.

Tận hưởng!

2

Dưới đây là một đơn giản, chung chung phiên bản:

template <typename T, size_t d1, size_t d2, size_t... ds> 
struct GetMultiDimArray 
{ 
    using type = std::array<typename GetMultiDimArray<T, d2, ds...>::type, d1>; 
}; 

template <typename T, size_t d1, size_t d2> 
struct GetMultiDimArray<T, d1, d2> 
{ 
    using type = std::array<std::array<T, d2>, d1>; 
}; 

template <typename T, size_t d1, size_t d2, size_t... ds> 
using MultiDimArray = typename GetMultiDimArray<T, d1, d2, ds...>::type; 

// Usage: 
MultiDimArray<int, 3, 2> arr {1, 2, 3, 4, 5, 6}; 
assert(arr[1][1] == 4); 
+0

Chỉ cần cẩn thận: các phương thức như 'std :: array :: size()' sẽ không trả về giá trị đúng. Ngoài ra, các phương thức như 'std :: array :: fill (value_type)' sẽ không hoạt động. – Ethan