如何编写带有两个占位符的lambda表达式,一个用于可调用对象,另一个用于函数参数,这样首先提供可调用对象将返回一元函数。
在下面的示例中,generate
应该是一个lambda表达式,其中包含可调用对象本身的第一个占位符,以及该参数的第二个占位符。调用generate(c)
应该返回一个只缺少函数调用参数的一元函数。事实上,它已经以某种方式返回类型bool
,正如静态断言所证明的那样。
#include <boost/lambda/bind.hpp>
struct Arg {
};
struct Callable : std::unary_function<Arg, bool> {
bool operator()( Arg const& a ) const { return true; }
};
int main( int argc, const char* argv[] ) {
BOOST_AUTO(generate, boost::lambda::bind(boost::lambda::_1, boost::lambda::protect(boost::lambda::_1)));
Callable c;
BOOST_AUTO(fn, generate(c));
BOOST_STATIC_ASSERT((boost::is_same<BOOST_TYPEOF(fn), bool>::value));
Arg a;
bool b = fn(a);
_ASSERT(b==true);
}
答案 0 :(得分:4)
如果使用Boost.Phoenix,答案会更容易一些:
#include <boost/phoenix/phoenix.hpp>
struct callable
{
typedef bool result_type;
bool operator()(int) const
{
return true;
}
};
int main()
{
using phx::bind;
using phx::lambda;
using phx::arg_names::_1;
using phx::local_names::_a;
auto generate = lambda(_a = _1)[bind(_a, _1)];
auto fn = generate(callable());
bool b = fn(8);
}
并不是说这个解决方案比OT发布的版本更通用。它可以与任何一元函数对象一起使用,无论什么参数,无论返回类型如何。
缺点是,你需要使用当前的升压干线......
答案 1 :(得分:1)
我已经解决了我自己的问题,虽然不像我希望的那样优雅:
struct FCreateBind {
typedef boost::_bi::bind_t<bool, Callable, boost::_bi::list2<boost::arg<1>, boost::arg<2> > > result_type;
result_type operator()( Callable const& c ) const {
return boost::bind<bool>(c, _1);
}
};
BOOST_AUTO(generate, boost::bind(FCreateBind(), _1));
BOOST_AUTO(fn, generate(Callable());
bool b = fn(Arg());
当然,在这个简单的例子中,我可以写BOOST_AUTO(generate, boost::lambda_1)
,因为Callable
本身就是可调用对象。但我正在寻找一种方法来预先设置Callable
的参数,因此生成的函数fn
是一个无效的函数。这个解决方案允许我在FCreateBind
内执行此操作。
FCreateBind
也可能被删除,但我还没有弄清楚如何定义指向重载全局函数boost::bind
的指针。
答案 2 :(得分:0)
虽然我不是100%确定我理解这个问题,但是以下代码 可能符合你的目的:
template< class R >
struct FCreateBind {
typedef boost::function< R() > result_type;
template< class T, class U >
result_type operator()( T const& x, U const& y ) const {
return boost::bind( x, y );
}
};
int main() {
BOOST_AUTO( generate, boost::bind( FCreateBind< bool >(), Callable(), _1 ) );
BOOST_AUTO( fn, generate( Arg() ) );
bool b = fn();
}
话虽这么说,可能这不像提问者那么漂亮
预计...
正如您所提到的,如果我们指定boost::bind
的一个重载
明确地,不需要FCreateBind
。
但是,就我所见,似乎没有可移植的指定方式
超载。
所以,在这种情况下,我们可能必须依赖boost
的内部
为了您的信息,我测试时可以编译以下代码:
int main() {
namespace bb = boost::_bi; // Sorry, for brevity
bb::bind_t< bb::unspecified, Callable, bb::list1< bb::value< Arg > > >
(*bi)( Callable, Arg ) = boost::bind< bb::unspecified, Callable, Arg >;
BOOST_AUTO( generate, boost::bind( bi, Callable(), _1 ) );
BOOST_AUTO( fn, generate( Arg() ) );
bool b = fn();
}
希望这有帮助