2012-01-11 11 views
7

mam n-wymiarowej Boost.MultiArray zainicjować w następujący sposób:Jedna linia initialiser dla 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); 

Więc mam 4 linie kodu, aby uzyskać MultiArray, ale chciałbym zrób to w jednym wierszu. Czy istnieje prosty sposób na wygenerowanie MultiArray o n wymiarach, każdy o długości size (czy mogę napisać arr(samevaluearray(n,size))) lub czy brakuje mi przydatnego konstruktora dla MultiArray?

Edit: To powinno działać bez zależności od pewnej wartości n, tj arr({{size,size}} będzie działać tylko dla n=2.

Ponieważ nie może być jasne: boost::multi_array<char,n>(boost::extents[4][4][4]) poprawnie inicjuje 4x4x4-tablicę, ale za każdym razem n zmienia się w kod źródłowy, każdy inicjalizacji musi być aktualizowana ręcznie, więc nie jest to opcja.

+2

OMG, to jest, że trudno owinąć to w funkcja, która akceptuje dwie liczby całkowite i zwraca 'boost :: multi_array'? –

+2

Lub dla prawdziwej zabawy, zapakuj go wewnątrz makra ;-) –

Odpowiedz

5

Okazuje się, std::vector ma konstruktora, który konstruuje wektor o stałej wartości powtarzanej n razy, więc możliwe rozwiązanie wygląda następująco:

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)); 

Powoduje zainicjowanie n-wymiarowej multi_array z wielkością każdego wymiaru ustawioną na rozmiar.

+0

Dobrze, nie rozwiązałeś problemu + zapomniałeś podać typ tablicy, którą tworzysz.Nie wspominając już o huuuuge narzut tworzenia wektora :-D –

+0

@ VladLazarenko Zapomniałem zmienić tstenner

+0

Cóż, to działałoby do pewnego stopnia. Ale obawiam się, że później wpadniesz na problem i będziesz musiał zmienić kod w całym miejscu. To dlatego, że mam wrażenie, że tak naprawdę nie rozumiesz roli 'const int n' w tym miejscu - nie jest to zmienna, ale stała ekspresja w czasie kompilacji. Teraz spróbuj zapisać funkcję, która mnoży dwie tablice, akceptuje "N", "rozmiar" i dwie tablice jako swoje argumenty. Twój kod szybko się zawiedzie, ponieważ 'n' nie będzie znany kompilatorowi podczas kompilacji. –

3

Z Boost Multi-Array documentation, tak, można zainicjować jedną linię:

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

W typedefs są dla czytelności, można równie dobrze zrobić dla przykładu:

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

Działa to, ale tylko dla n = 2. Dla każdego innego n, kod należy dostosować ręcznie. – tstenner

+2

@tstenner: Erm ... czego jeszcze można się spodziewać? Musisz dopasować * jakiś * kod co najmniej. Co chciałbyś zamiast tego stworzyć nowy 'multi_array'? – Xeo

+0

Właściwie znalazłeś dokładnie to, czego szukał OP, więc +1. Z jakiegoś powodu wciąż go nie ma i odpowiada na własne pytanie, mówiąc dokładnie to samo ... Smutne. –

8

można upakować tworzenie tablicy do funkcji pomocniczych:

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); 

Jeśli nie można używać auto, musisz powielać parametry szablonu:

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

make_regular_matrix funkcja może być skrócony do użycia std::vector, tak jak w twojej odpowiedzi; Nie wiem, czy ta implementacja byłaby lepsza. Celem funkcji pomocnika jest ukrycie tworzenie tablicy, ale inne wersje mogą być napisane, na przykład zainicjować elementów tablicy z danej wartości:

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