2012-05-15 30 views
12

Tôi chỉ viết một ví dụ đơn giản để kiểm tra boost :: bind. Tôi sử dụng nó để khởi tạo một hàm thành viên mẫu, nhưng nó sẽ không biên dịch với g ++ 4.6.0. Tôi không biết vấn đề là gì. Dưới đây là các mã:boost :: bind không biên dịch với hàm mẫu thành viên

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

Và g ++ cung cấp cho các lỗi sau đây:

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 

thể ai giúp giải thích điều này? Tại sao instantiation đầu tiên là OK trong khi thứ hai gây ra lỗi biên dịch?

+1

Đây là lạ .. –

+0

@SethCarnegie, 15 phút, chỉ cho rằng XD – chris

Trả lời

13

Có một tính năng (không hiển nhiên) là boost::bind có liên quan ở đây. http://www.boost.org/libs/bind/#nested_binds

Nếu bạn viết:

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 giả định rằng những gì bạn có nghĩa là "chạy func2 trên "Hello", sau đó chạy func1 vào kết quả". Điều này cho phép ứng dụng chức năng một phần thú vị hơn.

Trong chương trình của bạn, bạn có một biểu hiện mà số tiền:

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

Vì vậy boost::bind cố gắng để tìm ra cách để chạy DerivedFinishAction::Inc vào nó lập luận, vì vậy nó có thể vượt qua kết quả đó vào DerivedFinishAction::BindFunc<...>. Nhưng DerivedFinishAction::Inc trả về khoảng trống, không thể được chuyển vào DerivedFinishAction::BindFunc<...>. Vì vậy bạn nhận được một lỗi biên dịch:

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

Sửa: mỗi tài liệu, bạn có thể sử dụng protect để đạt được hành vi mong muốn của bạn:

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

Tính năng này của 'boost :: bind' cũng áp dụng cho' std :: bind'. – ildjarn

+0

Giải pháp tuyệt vời. Cảm ơn @Managu – airekans

Các vấn đề liên quan