4

私はboost::lambdaを学んでいますが、これまでの知識では解決できない状況を作り出すことができました。

明らかにboost::lambdaの腸内で、次の例は抽象クラスAbstractFooのインスタンス化を試み、ラムダ式のコンパイルを妨げます。問題は、インスタンス化しようとしている理由がわからないため、回避しようとできないことです。

次のことができるすべての 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、ブースト 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

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)

プレースホルダーがインラインでデレフされないようにポインターを引き出します。

Boost 1_47 を使用した VS でエラーなしでコンパイルすることを示唆するコメントから、この問題はその後 Boost で修正され、一種のバグであったと推測できます。

于 2011-07-27T09:48:49.267 に答える
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 に答える