2012-01-11 22 views
7

Tôi có một Boost.MultiArray n-chiều tôi khởi tạo như sau:Một dòng initialiser cho Boost.MultiArray

const int n=3, size=4; //# of dimensions and size of one dimension 
boost::multi_array<char,n> arr; 
boost::array<size_t,n> extents; //size of each dimension 
extents.assign(size); //assign size to each dimension -> {{4, 4, 4}} 
arr.resize(extents); 

Vì vậy, tôi có 4 dòng mã để có được những MultiArray, nhưng tôi muốn làm điều đó trong một dòng. Có cách nào đơn giản để tạo ra một MultiArray với n kích thước mỗi có chiều dài size (vì vậy tôi có thể viết arr(samevaluearray(n,size))) hoặc tôi đã bỏ lỡ một constructor tiện dụng cho MultiArray?

Chỉnh sửa: Nó sẽ hoạt động mà không phụ thuộc vào một giá trị nhất định của n, tức là arr({{size,size}} sẽ chỉ hoạt động cho n=2.

Vì có thể không rõ ràng: boost::multi_array<char,n>(boost::extents[4][4][4]) khởi tạo chính xác mảng 4x4x4, nhưng mỗi lần n được thay đổi trong mã nguồn, mỗi lần khởi chạy phải được cập nhật bằng tay, vì vậy nó không phải là tùy chọn.

+2

OMG, thật khó để bọc nó trong một hàm chấp nhận hai số nguyên và trả về 'boost :: multi_array'? –

+2

Hoặc để thực sự thú vị, hãy bọc nó bên trong một macro ;-) –

Trả lời

5

Hóa ra, std::vector có hàm tạo, tạo cấu trúc vectơ có giá trị không đổi lặp lại n lần, do đó, một giải pháp có thể có dạng như sau:

const int n=2, size=4; //# of dimensions and size of one dimension 
boost::multi_array<char,n> arr(std::vector<size_t>(n,size)); 

Việc này khởi tạo multi_array n chiều với kích thước của từng kích thước được đặt thành kích thước.

+0

Phải, bạn không giải quyết được sự cố + quên chỉ định loại mảng mà bạn đang tạo.Không phải đề cập đến một chi phí huuuuge của việc tạo ra một vector :-D –

+0

@VladLazarenko Quên thay đổi tstenner

+0

Vâng, nó sẽ hoạt động ở một mức độ nào đó. Nhưng tôi e rằng bạn sẽ gặp phải vấn đề sau này và sẽ phải thay đổi mã của bạn khắp nơi. Điều này là bởi vì tôi có cảm giác rằng bạn không thực sự hiểu vai trò của 'const int n' ở nơi này - nó không phải là một biến, mà là một biểu thức biên dịch không đổi. Bây giờ, hãy thử viết một hàm nhân hai mảng, chấp nhận 'N',' size' và hai mảng làm đối số của nó. Mã của bạn sẽ nhanh chóng thất bại vì 'n' sẽ không được trình biên dịch biết đến lúc biên dịch. –

3

Từ Boost Multi-Array documentation, vâng, bạn có thể khởi tạo nó một dòng:

typedef boost::multi_array<double, 3> array_type; 
typedef array_type::index index; 
array_type A(boost::extents[3][4][2]); 

Các typedefs được để có thể đọc, ai có thể cũng giống như dễ dàng làm ví dụ của bạn:

boost::multi_array<int, 2> arr(boost::extents[2][4]); 
+0

Tác phẩm này chỉ hoạt động, nhưng chỉ cho n = 2. Đối với các n khác, mã cần được điều chỉnh theo cách thủ công. – tstenner

+2

@tstenner: Erm ... bạn còn mong đợi điều gì nữa? Bạn phải điều chỉnh * một số * mã ít nhất. Thay vào đó, bạn muốn làm gì để tạo một 'multi_array' mới? – Xeo

+0

Thực tế, bạn đã tìm ra chính xác những gì OP đang tìm kiếm, vì vậy +1. Vì một lý do nào đó mà anh ta vẫn chưa hiểu và trả lời câu hỏi của chính mình, nói chính xác điều tương tự ... Buồn. –

8

Bạn có thể gói gọn việc tạo ra các mảng vào một chức năng helper:

template <typename T, size_t N> 
boost::multi_array<T, N> make_regular_matrix(const size_t m) 
{ 
    boost::multi_array<T, N> arr; 
    boost::array<size_t, N> extents; 
    extents.assign(m); 
    arr.resize(extents); 

    return arr; 
} 

const int n = 3; 
int size = 4; // Can be const as well, but this is not mandatory 

auto arr = make_regular_matrix<char, n>(size); 

Nếu bạn không thể sử dụng auto, bạn sẽ phải lặp lại các thông số mẫu:

boost::multi_array<char, n> arr = make_regular_matrix<char, n>(size); 

Các Chức năng make_regular_matrix có thể được rút ngắn để sử dụng std::vector, như bạn đã làm trong câu trả lời của mình; Tôi không biết liệu việc triển khai này có tốt hơn không. Mục đích của chức năng trợ giúp là ẩn việc tạo mảng, nhưng các phiên bản khác có thể được viết, ví dụ để khởi tạo các phần tử mảng với một giá trị đã cho:

template <size_t N, typename T> //switched order for deduction 
boost::multi_array<T, N> make_regular_matrix(const size_t m, const T & value) 
{ 
    boost::multi_array<T, N> arr(std::vector<size_t>(n, m)); 

    std::fill(arr.data(), arr.data() + arr.num_elements(), value); 

    return arr; 
} 

auto arr = make_regular_matrix<4>(3, 'z'); //creates a 3x3x3x3 matrix 
              //filled with 'z's 
Các vấn đề liên quan