4

我正在学习 boost::lambda 并且我已经设法创造了一个我目前所知道的无法解决的情况。

显然,在 boost::lambda 的内部,以下示例导致尝试实例化抽象类 AbstractFoo,并阻止 lambda 表达式编译。问题是我不知道它为什么要实例化它,所以我无法尝试解决它。

任何能够:

  • 告诉我为什么会这样?
  • 建议解决方法?

例子:

#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>


struct AbstractFoo
{
    typedef boost::shared_ptr<AbstractFoo> Ptr;
    virtual int it() const = 0;
};

struct Bar : public AbstractFoo
{
    typedef boost::shared_ptr<Bar> Ptr;
    virtual int it() const { return 3; }
};

typedef AbstractFoo Foo;  // Comment this out
//typedef Bar Foo;        // and this in to make this example compilable

int main()
{
  namespace bll = boost::lambda;

  boost::function< bool (const Foo::Ptr &)> func;
  func = (bll::protect(bll::bind( &Foo::it, *bll::_1))(bll::_1) == 3);

  return 0;
}

这无法编译(在 gcc 4.4.3 上,boost 1_40)并出现怪物模板错误,其中重要的部分似乎是:

error: cannot declare field 
           ‘boost::tuples::cons<AbstractFoo,boost::tuples::null_type>::head’ 
       to be of abstract type ‘AbstractFoo’
       because the following virtual functions are pure within ‘AbstractFoo’:
            virtual int AbstractFoo::it() const
4

2 回答 2

1

正如您所发现的,您不能这样做,因为需要复制对象,但在这种情况下它不能被实例化,因为它包含一个纯虚方法。最简单的解决方案是使用指针传递它:

#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>

#include <iostream>

struct AbstractFoo
{
    typedef boost::shared_ptr<AbstractFoo> Ptr;
    virtual int it() const = 0;
};

struct Bar : public AbstractFoo
{
    typedef boost::shared_ptr<Bar> Ptr;
    virtual int it() const { return 3; }
};

typedef AbstractFoo Foo;  // Comment this out
//typedef Bar Foo;        // and this in to make this example compilable

int main()
{
  namespace bll = boost::lambda;

  boost::function< bool ( const Foo * )> func;
  func = ( bll::protect( bll::bind( &Foo::it, bll::_1 ) )( bll::_1 ) == 3);
  //func = bll::bind( &Foo::it, bll::_1 );

  Foo::Ptr p( new Bar );
  std::cout << std::boolalpha << func( p.get() ) << std::endl;
}

更准确地说,这个:

*bll::_1

需要实例化和复制 AbstractFoo 类型的对象

于 2011-07-27T09:30:35.733 回答
1

摆脱 JVo 的回答,以下解决该问题的方法:

func3 = (bll::protect(bll::bind( &Foo::it, 
                                 bll::bind( &Foo::Ptr::get, 
                                            bll::_1         ))) (bll::_1) == 2);

在哪里

bll::bind( &Foo::Ptr::get, bll::_1)

拉出指针,使占位符不被取消排列。

从建议在 VS 中使用 Boost 1_47 编译没有错误的评论中,我可能猜想这个问题已经在 boost 中得到修复,并且它是一种错误。

于 2011-07-27T09:48:49.267 回答