由于抽象模板arg的实例化,Boost::lambda表达式编译失败.任何解释和/或解决方法

boost::lambda expression fails to compile because of instantiation of abstract template arg. Any explanation and/or work arounds?

本文关键字:失败 编译 表达式 lambda 任何 方法 解决 解释 Boost 抽象 于抽象      更新时间:2023-10-16

我在学习boost::lambda的过程中,我已经设法创造了一个我无法用我目前所知道的来解决的情况。

显然在boost::lambda的内部,下面的示例导致尝试实例化抽象类AbstractFoo,并阻止lambda表达式编译。问题是,我不知道为什么它试图实例化它,所以我不能尝试围绕它工作。

任何boost::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

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

#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类型的对象

摘自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中修复了,这是一种bug。