eud*_*xos 7 c++ lambda boost-python c++11
我想用C++ 11 lambda表达式作为访问功能boost::python的add_property,沿着下面的内容(拉姆达并不是必需在这个例子中,但将需要更复杂的东西拉姆达内部发生,如验证):
#include<boost/python.hpp>
struct A{
A(): a(2){};
int a;
};
BOOST_PYTHON_MODULE(boost_python_lambda)
{
boost::python::class_<A>("A")
// .def_readonly("a",&A::a) // the classical way: works fine
.add_property("a",[](const A& a){return a.a;})
;
}
Run Code Online (Sandbox Code Playgroud)
但是,使用clang ++(版本3.2)编译和-std=c++11(结果与g ++ 4.7相同),我收到此错误:
/usr/include/boost/python/class.hpp:442:66: error: no matching function for call to 'get_signature'
return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
^~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/python/class.hpp:422:22: note: in instantiation of function template specialization 'boost::python::class_<A,
boost::python::detail::not_specified, boost::python::detail::not_specified,
boost::python::detail::not_specified>::make_fn_impl<A, <lambda at boost_python_lambda.cpp:12:21> >' requested here
return this->make_fn_impl(
^
/usr/include/boost/python/class.hpp:309:40: note: in instantiation of function template specialization 'boost::python::class_<A,
boost::python::detail::not_specified, boost::python::detail::not_specified,
boost::python::detail::not_specified>::make_getter<<lambda at boost_python_lambda.cpp:12:21> >' requested here
base::add_property(name, this->make_getter(fget), docstr);
^
boost_python_lambda.cpp:12:4: note: in instantiation of function template specialization 'boost::python::class_<A,
boost::python::detail::not_specified, boost::python::detail::not_specified,
boost::python::detail::not_specified>::add_property<<lambda at boost_python_lambda.cpp:12:21> >' requested here
.add_property("a",[](const A& a){return a.a;})
^
Run Code Online (Sandbox Code Playgroud)
我尝试将lambda包装进去std::function<int(const A&)>(...),但这对参数演绎没有帮助.任何的想法?
两年后跳进这里,Boost.Python确实不支持包装函数对象.但是你的lambda没有捕获任何东西.因此,它可以显式转换为函数指针:
BOOST_PYTHON_MODULE(boost_python_lambda)
{
boost::python::class_<A>("A")
// .def_readonly("a",&A::a) // the classical way: works fine
.add_property("a", +[](const A& a){return a.a;})
???
;
}
Run Code Online (Sandbox Code Playgroud)
所有你需要的是+.
使用该make_function()函数创建 Python 可调用对象。如果 Boost.Python 无法推导出函数对象签名,那么签名必须明确提供为MPL 前端可扩展序列。例如,lambda[](const A& a) { return a.a; }返回 anint并接受const A&,因此可以boost::mpl::vector<int, const A&>()用于签名。
这是一个完整的示例,演示了使用指向数据成员的指针、将非捕获 lambda 转换为函数以及使用 lambda/函子:
#include <boost/python.hpp>
struct A
{
A(): a(2) {};
int a;
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<A>("A")
// Expose pointer-to-data-member.
.add_property("a1", &A::a)
// Cast non-capturing lambda to a function.
.add_property("a2", +[](const A& a) { return a.a; })
// Make a python function from a functor.
.add_property("a3", python::make_function(
[](const A& a) { return a.a; },
python::default_call_policies(),
boost::mpl::vector<int, const A&>()))
;
}
Run Code Online (Sandbox Code Playgroud)
互动使用:
>>> import example
>>> a = example.A()
>>> assert(a.a1 == 2)
>>> assert(a.a2 == 2)
>>> assert(a.a3 == 2)
Run Code Online (Sandbox Code Playgroud)
另一种基于记录行为的非侵入式方法是将 lambda 编写为非成员函数,然后将其作为fget参数公开。虽然不像 lambda 那样简洁,但它仍然允许在访问成员变量时进行其他功能,例如验证。
#include <boost/python.hpp>
struct A{
A(): a(2){};
int a;
};
int get_a(const A& a)
{
// do validation
// do more complicated things
return a.a;
}
BOOST_PYTHON_MODULE(example)
{
boost::python::class_<A>("A")
.add_property("a", &get_a);
;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3062 次 |
| 最近记录: |