2011-12-12 11 views
10

Ho un multiray 3D e vorrei creare sezioni 2D usando le dimensioni specificate in fase di esecuzione. Conosco l'indice della dimensione degenerata e l'indice di una sezione che voglio estrarre in quella dimensione degenerata. Attualmente la brutta soluzione è la seguente:Come specificare la dimensione degenerata di boost multi_array in fase di runtime?

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]]; 
} 

C'è un modo più bello di costruire l'oggetto index_gen? Qualcosa del genere:

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

Sembra ogni chiamata successiva al boost :: :: indici operator [] restituisce un tipo diverso a seconda della dimensionalità (cioè il numero di chiamate precedenti), quindi non c'è modo di utilizzare un variabile singola, che può contenere l'oggetto index_gen temporaneo.

+0

+1 per una domanda chiara che utilizza una matrice multidimensionale sana, non quella roba C! :) – Xeo

risposta

3

prega, provate questo. Сode ha uno svantaggio: si riferisce alla variabile range_ array dichiarata al namespace boost :: detail :: 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

Questo è fantastico e funziona. Mi dispiace di averlo perso quando la taglia era ancora attiva, quindi ti darò la tua 100 reputazione votando per tutte le 18 risposte che hai nella pagina del tuo profilo. Anche se è una specie di hack del sistema di classificazione, non conosco nessun altro modo per farlo. –

+0

Ti è venuto in mente che leggendo il codice sorgente di multi_array o lo hai raccolto dai documenti? –

+0

Grazie mille per la reputazione :) Sono contento di sapere che questo codice ti ha aiutato. Per trovare una soluzione, ho lavorato solo con la fonte di multi_array e la conoscenza applicata di C++. – alexander

-2

Quello che stai cercando di fare è spostare una variabile dal tempo di esecuzione al tempo di compilazione. Questo può essere fatto solo con una catena di istruzioni if else o con una dichiarazione switch.

Un esempio semplificato

// 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 
} 
Problemi correlati