如何编写返回新仿函数的 boost::lambda 仿函数

发布于 2024-10-21 01:38:18 字数 783 浏览 12 评论 0原文

如何编写带有两个占位符的 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);
}

How can I write a lambda expression with two placeholders, one for the callable object, and one for the function argument, such that supplying the callable object first returns a unary function.

In the example below, generate should be a lambda expression with the first placeholder for the callable object itself, and the second placeholder for the argument. Calling generate(c) should return a unary function that is only missing the function call argument. In fact, it somehow returns type bool already, as proved by the static assert.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

彩扇题诗 2024-10-28 01:38:18

如果使用 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 发布的版本更通用。它可以与任何一元函数对象一起使用,无论参数是什么,无论返回类型是什么。

缺点是,您需要使用当前的升压主干......

If using Boost.Phoenix the answer would have been a little easier:

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

Not that this solution is far more generic than the version posted by the OT. It can be used with any unary function object, no matter what argument, no matter what return type.

The downside, you need to use the current boost trunk ...

楠木可依 2024-10-28 01:38:18

我已经解决了自己的问题,尽管没有我希望的那么优雅:

   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 code> 本身就是可调用对象。但我一直在寻找一种方法来预先设置 Callable 的参数,以便生成的函数 fn 是一个空函数。该解决方案允许我在 FCreateBind 内执行此操作。

FCreateBind 或许也可以被消除,但我还没有弄清楚如何定义指向重载的全局函数 boost::bind 的指针。

I have solved my own problem, albeit not as elegantly as I had hoped:

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

Of course, in this simple example I could just write BOOST_AUTO(generate, boost::lambda_1) since Callable itself is the callable object. But I was looking for a way to set the arguments of Callable beforehand so the generated function fn is a nullary function. This solution would let me do this inside FCreateBind.

FCreateBind can probably be eliminated as well, but I have not yet figured out how to define the pointer to the overloaded global function boost::bind.

堇色安年 2024-10-28 01:38:18

虽然我不是 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();
}

希望这有帮助

Though I'm not 100% sure I understand the question, the following code
might meet your purpose:

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

That being said, probably this isn't as pretty as the questioner
expects...
As you mentioned, if we specify one of the overloads of boost::bind
explicitly, FCreateBind wouldn't be needed.
However, as far as I saw, there seems not to be the portable way to specify
the overload.
So, in this case, probably we have to depend on the internal of boost.
For your information, the following code could be compiled when I tested:

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

Hope this helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文