2011-12-12 8 views
10

Mam 3D multi_array i chciałbym, aby plasterki 2D przy użyciu wymiarów określonych w czasie wykonywania. Znam indeks zdegenerowanego wymiaru i indeks kawałka, który chcę wyodrębnić w tym zdegenerowanym wymiarze. Obecnie brzydkie obejście wygląda następująco:Jak określić zdegenerowany wymiar boost multi_array w czasie wykonywania?

if (0 == degenerate_dimension) 
{ 
    Slice slice = input_array[boost::indices[slice_index][range()][range()]]; 
} 
else if (1 == degenerate_dimension) 
{ 
    Slice slice = input_array[boost::indices[range()][slice_index][range()]]; 
} 
else if (2 == degenerate_dimension) 
{ 
    Slice slice = input_array[boost::indices[range()][range()][slice_index]]; 
} 

Czy istnieje lepszy sposób na skonstruowanie obiektu index_gen? Coś takiego:

var slicer; 
for(int i = 0; i < 3; ++i) { 
    if (degenerate_dimension == i) 
     slicer = boost::indices[slice_index]; 
    else 
     slicer = boost::indices[range()]; 
} 
Slice slice = input_array[slicer]; 

Wydaje każdego kolejnego połączenia do boost :: indeksy :: operator [] zwraca inny typ w zależności od wymiarowości (czyli liczbę poprzednich wywołań), więc nie ma sposobu, aby użyć pojedyncza zmienna, która może pomieścić tymczasowy obiekt index_gen.

+0

+1 za jasne pytanie za pomocą rozsądnej wielowymiarowej tablicy, nie że C rzeczy! :) – Xeo

Odpowiedz

3

Proszę, spróbuj tego. Kod ma jedną wadę - odnosi się do zmiennej field_rozmianowej zadeklarowanej w przestrzeni nazw :: query :: multi_array.

#include <boost/multi_array.hpp>                                

typedef boost::multi_array<double, 3> array_type;                            
typedef boost::multi_array_types::index_gen::gen_type<2,3>::type index_gen_type;                     
typedef boost::multi_array_types::index_range range;                           

index_gen_type                                      
func(int degenerate_dimension, int slice_index)                            
{                                        
    index_gen_type slicer;                                   
    int i;                                      
    for(int i = 0; i < 3; ++i) {                                
     if (degenerate_dimension == i)                               
      slicer.ranges_[i] = range(slice_index);                           
     else                                     
      slicer.ranges_[i] = range();                              
    }                                       
    return slicer;                                    
}                                        

int main(int argc, char **argv)                                
{                                        
    array_type myarray(boost::extents[3][3][3]);                            
    array_type::array_view<2>::type myview = myarray[ func(2, 1) ];                       
    return 0;                                     
} 
+0

To jest świetne i działa. Przykro mi, że przegapiłem to, gdy nagroda była nadal aktywna, więc zamierzam dać ci 100 punktów reputacyjnych, głosując na wszystkie 18 odpowiedzi, które otrzymałeś na swojej stronie profilu. Chociaż jest to rodzaj hackowania systemu ocen, nie znam innego sposobu, aby to zrobić. –

+0

Czy wymyśliłeś czytanie kodu źródłowego multi_array, czy podniosłeś go z dokumentacji? –

+0

Dziękuję bardzo za reputację :) Cieszę się, że ten kod ci pomógł. Aby znaleźć rozwiązanie, pracowałem tylko ze źródłem multi_array i stosowałem znajomość C++. – alexander

-2

To, co próbujesz zrobić, to przenieść zmienną z czasu wykonywania do czasu kompilacji. Można to zrobić tylko z łańcuchem oświadczeń if else lub oświadczeniem switch.

Uproszczony przykład

// print a compile time int 
template< int I > 
void printer(void) 
{ 
    std::cout << I << '\n'; 
} 

// print a run time int 
void printer(int i) 
{ 
    // translate a runtime int to a compile time int 
    switch(i) 
    { 
     case 1: printer<1>(); break; 
     case 2: printer<2>(); break; 
     case 3: printer<3>(); break; 
     case 4: printer<4>(); break; 
     default: throw std::logic_error("not implemented"); 
    } 
} 

// compile time ints 
enum{ enum_i = 2 }; 
const int const_i = 3; 
constexpr i constexper_i(void) { return 4; } 

// run time ints 
extern int func_i(void); // { return 5; } 
extern int global_i; // = 6 

int main() 
{ 
    int local_i = 7; 
    const int local_const_i = 8; 

    printer<enum_i>(); 
    printer<const_i>(); 
    printer<constexpr_i()>(); 
    //printer<func_i()>(); 
    //printer<global_i>(); 
    //printer<local_i>(); 
    printer<local_const_i>(); 

    printer(enum_i); 
    printer(const_i); 
    printer(constexpr_i()); 
    printer(func_i()  ); // throws an exception 
    printer(global_i  ); // throws an exception 
    printer(local_i  ); // throws an exception 
    printer(local_const_i); // throws an exception 
} 
Powiązane problemy