2011-12-12 28 views
10

Tôi có một multi_array 3D và tôi muốn tạo các lát 2D bằng cách sử dụng các kích thước được chỉ định trong thời gian chạy. Tôi biết chỉ số của thứ nguyên thoái hóa và chỉ mục của một lát mà tôi muốn trích xuất trong thứ nguyên thoái hóa đó. Hiện tại, giải pháp xấu xí trông giống như vậy:Làm thế nào để xác định kích thước thoái hóa của boost multi_array khi chạy?

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ó cách nào đẹp hơn để xây dựng đối tượng index_gen không? Something như thế:

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

Dường như mỗi cuộc gọi tiếp theo để thúc đẩy :: chỉ số :: operator [] trả về một kiểu khác nhau tùy thuộc vào chiều (tức là số lượng cuộc gọi trước đó), vì vậy không có cách nào để sử dụng một biến duy nhất, có thể giữ đối tượng index_gen tạm thời.

+0

+1 cho câu hỏi rõ ràng bằng cách sử dụng mảng đa chiều sane chứ không phải nội dung C! :) – Xeo

Trả lời

3

Hãy thử này. Сode có một bất lợi - nó đề cập đến biến array_ array được khai báo tại boost :: detail :: multi_array namespace.

#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

Điều này thật tuyệt vời và nó hoạt động. Tôi xin lỗi tôi đã bỏ lỡ nó khi tiền thưởng vẫn còn, vì vậy tôi sẽ cung cấp cho bạn 100 danh tiếng của bạn bằng cách bỏ phiếu cho tất cả 18 câu trả lời bạn có ở trang hồ sơ của bạn. Mặc dù nó là loại hack của hệ thống đánh giá, tôi không biết bất kỳ cách nào khác để làm điều đó. –

+0

Bạn đã nghĩ ra rằng đọc mã nguồn của multi_array hoặc bạn đã nhặt nó từ tài liệu chưa? –

+0

Cảm ơn bạn rất nhiều vì danh tiếng :) Rất vui khi biết rằng mã này đã giúp bạn. Để tìm ra một giải pháp, tôi chỉ làm việc với nguồn của multi_array và áp dụng kiến ​​thức về C++. – alexander

-2

Những gì bạn đang cố gắng làm là di chuyển một biến từ thời gian chạy để biên dịch thời gian. Điều này chỉ có thể được thực hiện với một chuỗi các câu lệnh if else hoặc tuyên bố switch.

Một ví dụ đơn giản

// 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 
} 
Các vấn đề liên quan