开发者

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

I'm in the process of learning boost::lambda and I've managed to create a situation that I can't resolve with what I know so far.

Apparently in the bowels of boost::lambda, the following example causes the attempted instantiation of abstract class AbstractFoo, and prevents the lambda expression from compiling. The problem is that I don't know why it is trying to instantiate it so I cant try to work around it.

Any boost::lambda experts that can:

  • give me a clue as to why this is happening?
  • suggest a work around?

Example:

#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp开发者_JAVA技巧>


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

This fails to compile (on gcc 4.4.3, boost 1_40) with a monster template error the important part of which seems to be:

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


As you discovered, you can not do that, because the object needs to be copied, but in this case it can not be instantiated because it contains a pure virtual method. The simplest solution is to pass it using a pointer :

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

To be more precise, this :

*bll::_1

needs to instantiate and copy object of type AbstractFoo


Riffing off of JVo's answer, the following works around the issue:

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

where

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

Pulls out the pointer so that the place holder is not dereffed in line.

From the comments suggesting compiling without error in VS with Boost 1_47 I might guess that the issue has since been fixed in boost, and that it was a sort of bug.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜