2011-05-03 153 views
4

說我有一個模板動作爲什麼我的C++ lambda函數不能被捕獲?

template <class ArgT> 
struct Action 
{ 
    Action(::boost::function< void(ArgT) > func) 
     : func_(func) 
    { 
    } 

    void operator()(ArgT arg) 
    { 
     func_(arg); 
    } 

private: 
     ::boost::function< void(ArgT) > func_; 
}; 

我用行動像這樣:

class XCallbackInvoker : public CallbackInvoker<X> 
{ 
public: 
    XCallbackInvoker (Action<int> callback) 
     : CallbackInvoker<X>(
      Action< ::boost::shared_ptr<X> >(
       [&callback](::boost::shared_ptr<X> x) -> void 
       { 
        Action<int> callbackCopy = callback; 
        callbackCopy(x->errorCode()); 
       })) 
    { 
    } 
}; 

編輯:CallbackInvoker添加

template <class T> 
class CallbackInvoker : public ICallbackInvoker 
{ 
public: 
    CallbackInvoker(Action< ::boost::shared_ptr<T> > callback) 
     : callback_(callback) 
    { 
    } 

    void invoke(::boost::shared_ptr<IBase> message) 
    { 
     callback_(::boost::static_pointer_cast<T>(message)); 
    } 

private: 
    Action< ::boost::shared_ptr<T> > callback_; 
}; 

現在,如果我不使用臨時複製回調引用的值,它編譯得很好,但我得到一個運行時錯誤(我的回調丟失)。如果我通過值(即[=callback])傳遞我的lambda回調參數並且不使用臨時值,那麼會出現編譯錯誤(我的表達式會丟失一些const-volatile限定符...)

爲什麼不能我通過值捕獲我的lambda函數,而不是使用臨時?

+1

能請你也張貼'CallbackInvoker <>'所以我們可以試試這個編譯自己的代碼? – ildjarn 2011-05-03 13:26:48

+0

@ildjarn,謝謝。 – 2011-05-03 13:33:22

+0

如果你有編譯器錯誤,通常最好把它複製到問題中,而不是將它壓縮成「我的表達式會丟失一些const-volatile限定符」。該錯誤信息可能暗示了觸發問題的特定用途。 – 2011-05-03 13:59:57

回答

11

如果通過複製捕獲,則默認情況下不能修改它,因爲lambda的operator()被聲明爲const。您需要添加mutable到您的拉姆達允許捕獲的變量的修改:

XCallbackInvoker (Action<int> callback) 
    : CallbackInvoker<X>(
     Action< ::boost::shared_ptr<X> >(
      [callback](::boost::shared_ptr<X> x) mutable -> void 
      { 
       callback(x->errorCode()); 
      })) 
{ 
} 
+0

這是非常漂亮的信息。 thx – sehe 2011-05-03 13:33:49

+0

謝謝安東尼,我不知道lambdas上的可變技巧。 – 2011-05-03 13:35:29

+4

或者將'struct Action'的'operator()'聲明爲'const'。 – 2011-05-03 13:40:11

相關問題