2012-05-15 74 views
12

我只寫了一個簡單的例子來測試boost :: bind。我用它來實例化一個模板成員函數,但它不會用g ++ 4.6.0進行編譯。我不知道有什麼問題。 下面的代碼:boost :: bind不能編譯成員模板函數

#include <boost/bind.hpp> 

struct Functor 
{ 
    void operator()() 
    { 

    } 
}; 

struct DerivedFinishAction 
{ 
    DerivedFinishAction() 
    {} 

    void Inc() 
    { 

    } 

    template <typename T> 
    void TmplFunc(T t) 
    { 
    (boost::bind(&DerivedFinishAction::BindFunc<T>, this , t))(); 
    } 

    template <typename T> 
    void BindFunc(T t) 
    { 
    t(); 
    } 

    void Func() 
    { 
    Functor f; 
    TmplFunc(f); // this is OK 
    TmplFunc(boost::bind(&DerivedFinishAction::Inc, this)); // compile error 
    } 
}; 

int main(int argc, char *argv[]) 
{ 

    return 0; 
} 

和g ++提供了以下錯誤:

In file included from /usr/include/boost/bind.hpp:22:0, 
       from testBind.cpp:1: 
/usr/include/boost/bind/bind.hpp: In member function ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf1<void, DerivedFinishAction, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, A = boost::_bi::list0, A1 = boost::_bi::value<DerivedFinishAction*>, A2 = boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > >]’: 
/usr/include/boost/bind/bind_template.hpp:20:59: instantiated from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = boost::_mfi::mf1<void, DerivedFinishAction, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, L = boost::_bi::list2<boost::_bi::value<DerivedFinishAction*>, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, boost::_bi::bind_t<R, F, L>::result_type = void]’ 
testBind.cpp:24:5: instantiated from ‘void DerivedFinishAction::TmplFunc(T) [with T = boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > >]’ 
testBind.cpp:37:58: instantiated from here 
/usr/include/boost/bind/bind.hpp:313:9: error: invalid use of void expression 

任何人可以幫助解釋一下嗎?爲什麼第一個實例化是好的,而第二個實例化會導致編譯錯誤?

+1

這很奇怪.. –

+0

@SethCarnegie,15分鐘,只是爲了XD – chris

回答

13

這裏涉及的boost::bind有一個(非顯而易見的)特徵。 http://www.boost.org/libs/bind/#nested_binds

如果你寫:

void func1(int len) {return len+1;}; 
int func2(std::string str) {return str.length();}; 

assert(
    boost::bind(func1, boost::bind(func2, _1))("Hello") 
    == 6); 

boost::bind假定你的意思是 「上"Hello"運行func2,然後運行的結果func1」。這允許更有趣的部分功能應用。

在你的程序中,你有這相當於一個表達式:

boost::bind(&DerivedFinishAction::BindFunc<...>, 
      this, 
      boost::bind(&DerivedFinishAction::Inc, this)) 

所以boost::bind試圖找出如何在其上運行參數DerivedFinishAction::Inc,所以它可以是結果傳遞到DerivedFinishAction::BindFunc<...>。但DerivedFinishAction::Inc返回void,無法傳入DerivedFinishAction::BindFunc<...>。因此,你得到一個編譯錯誤:

/usr/include/boost/bind/bind.hpp:313:9: error: invalid use of void expression 

編輯:每文檔,你可以用protect來達到你想要的行爲:

#include <boost/bind/protect.hpp> 
... 
TmplFunc(boost::protect(boost::bind(&DerivedFinishedAction::Inc, this))); // no longer an error 
... 
+0

'boost :: bind'的這個特性也適用於'std :: bind'。 – ildjarn

+0

解決方案非常棒。謝謝@Managu – airekans

相關問題