2011-03-31 98 views
4

我有一個C++類,通過使用boost::range提供函數返回範圍來公開集合。使boost :: python :: range接受... boost ::範圍

爲了這個類導出到蟒蛇與boost::python,我使用功能boost::python::range,它可以接受兩個參數:類返回集合的開始和結束迭代器的成員函數。

我想避免爲每個集合手動編寫開始/結束對,因爲我已經提供了範圍。但我不能設法寫一個包裝在boost :: python :: range接受作爲參數返回一個範圍的成員函數。有任何想法嗎? (我實際上有超過一個類,這是模板化的,所以模板函數作爲模板參數的模板類的成員函數的地址將不起作用,我的編譯器說)

我會接受一個C++ 0x解決方案,如果編譯與g ++ - 4.6。

編輯: 說我有這個類:如問一個示例代碼

struct A 
{ 
    std::vector<int> c; 
    typedef boost::sub_range<std::vector<int> > c_range; 
    c_range getc() { return c; } 
}; 

以從getc方法Python的迭代器,我現在這兩個成員函數添加到A類:

c_range::iterator c_begin() { return getc().begin(); } 
c_range::iterator c_end() { return getc().end(); } 

,然後將它們公開這樣的:

boost::python::class_<A>("A") 
    .def("getc", boost::python::range(&A::c_begin, &A::c_end)); 

有沒有直接寫類似的方式:

.def("getc", pyrange(&A::getc)); 

並避免寫c_beginc_end

+0

您可以顯示代碼形式的例子嗎? – 2011-03-31 18:01:44

回答

4

解決方法是使用帶有四個模板參數的更一般形式range:將開始/結束訪問器創建爲boost::bind'ed對象,然後指定目標模板參數range。對於常量迭代器,該代碼滿足我的需求:

namespace py = boost::python 
template <class T, class Return> 
struct range_accessor { 
    typedef Return (T::*RA)() const; 
    static typename Return::const_iterator 
    begin(RA ra, const T& t) { 
     return (t.*ra)().begin(); 
    } 
    static typename Return::const_iterator 
    end(RA ra, const T& t) { 
     return (t.*ra)().end(); 
    } 

    static py::object 
    pyrange(RA ra) { 
     auto b = boost::bind(&range_accessor::begin, ra, _1); 
     auto e = boost::bind(&range_accessor::end, ra, _1); 
     return py::range< 
      boost::python::objects::default_iterator_call_policies, 
      T> // the "Target" parameter, which can 
      // not be deduced from a bind object 
     (b,e); 
    } 
}; 

template <class T, class Return> 
py::object pyrange(Return (T::*ra)() const) { 
    return range_accessor<T, Return>::pyrange(ra); 
} 

編輯:稍微緊湊的解決方案,通過使用內部函數定義的局部結構:

template <class T, class Return> 
py::object 
pyrange(Return (T::*ra)() const) { 
    typedef Return (T::*RA)() const; 
    struct accessor { 
     static typename Return::const_iterator 
     begin(RA ra, const T& t) { 
      return (t.*ra)().begin(); 
     } 
     static typename Return::const_iterator 
     end(RA ra, const T& t) { 
      return (t.*ra)().end(); 
     } 
    }; 
    return py::range<boost::python::objects::default_iterator_call_policies, T> 
     (boost::bind(&accessor::begin, ra, _1), 
     boost::bind(&accessor::end, ra, _1)); 
} 
+0

啊,一直在尋找這樣的代碼示例..有點遲了,但請你能告訴我們你是如何在'.def'方法中暴露給Python的?我剛纔問了一個非常類似的問題[這裏](http://stackoverflow.com/questions/15659610/how-to-expose-c-classes-with-const-iterator?noredirect=1#comment22225235_15659610) – 2013-03-27 13:53:32