2011-12-12 70 views
10

我有一个3D multi_array,我想使用运行时指定的尺寸制作2D切片。我知道退化维度的索引和我想从退化维度中提取的片段的索引。目前丑陋的解决方法如下:如何在运行时指定boost multi_array的退化维?

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

有没有更漂亮的方法来构造index_gen对象? 类似的东西:

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

看来以后每次调用的boost ::指数:: operator []的返回一个不同类型的视维(即以前的呼叫数),所以没有办法用一个单个变量,可以容纳临时的index_gen对象。

+0

+1对于一个明确的问题,使用一个理智的多维数组,而不是C的东西! :) – Xeo

回答

3

请试试这个。 Сode有一个缺点 - 它是指在boost :: detail :: multi_array命名空间中声明的ranges_数组变量。

#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

这是伟大的,它的工作原理。对不起,当奖金还在时我错过了,所以我会给你100个声望,通过投票你的个人资料页面上的所有18个答案。虽然它是评级系统的破绽,但我不知道有任何其他方式可以做到这一点。 –

+0

您是否想出了阅读multi_array的源代码或者您是否从文档中选取它? –

+0

非常感谢您的声誉:)很高兴听到这段代码对您有所帮助。为了找到解决方案,我只使用multi_array的源代码并应用了C++的知识。 – alexander

-2

你要做的是从运行时间移动一个变量来编译时间。这只能通过一条if else声明或switch声明来完成。

一个简单的例子

// 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 
} 
相关问题