【问题标题】:making boost::python::range accepting... a boost::range使 boost::python::range 接受...一个 boost::range
【发布时间】:2011-03-31 17:36:26
【问题描述】:

我有一个 c++ 类,它通过提供返回范围的函数来公开集合,使用 boost::range

为了用boost::python将这个类导出到python,我使用了函数boost::python::range,它可以接受两个参数:返回集合的开始和结束迭代器的类的成员函数。

我想避免为每个集合手动编写开始/结束对,因为我已经提供了范围。但是我无法在 boost::python::range 上编写一个包装器,接受一个返回范围的成​​员函数作为参数。有任何想法吗? (实际上我有不止一个类,它们是模板化的,所以模板函数将模板类的成员函数的地址作为模板参数将不起作用,我的编译器说)

如果可与 g++-4.6 编译,我将接受 c++0x 解决方案。

编辑:一个示例代码: 说我有这门课:

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

【问题讨论】:

  • 你能以代码形式展示一个例子吗?

标签: c++ boost-python


【解决方案1】:

解决方案是使用带有四个模板参数的更通用的range 形式:将开始/结束访问器创建为boost::bind'ed 对象,然后指定range 的目标模板参数。对于 const 迭代器,这段代码满足了我的需求:

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

【讨论】:

  • 啊,一直在寻找这样的代码示例。。问的有点晚了,但请你能说明一下你是如何在.def 方法中将它暴露给 Python 的吗?我刚刚问了一个非常相似的问题here
猜你喜欢
  • 1970-01-01
  • 2017-08-01
  • 2015-12-29
  • 1970-01-01
  • 2018-12-25
  • 2012-10-22
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
相关资源
最近更新 更多