1

我想一個通用的boost::function<void(void)>連接到許多的boost ::不同簽名的signals2使用boost :: is_same在C++模板。我能使用Boot ::拉姆達::綁定通過將返回值作爲綁定參數的一部分做結合部,但有一個問題,當返回類型爲void如何一起的boost ::拉姆達::綁定

例子:

template<typename S> 
class signal 
{ 
Connection VoidConnect(boost::function<void(void)> callback) 
    { 
    //if(boost::is_same<void, typename S::result_type>::value) // Doesn't seem to work 
    if (boost::is_void<typename S::result_type>::value) // Doesn't seem to work 
    { 
     //GetSignal returns the actual boost signal 
     // typename 'S' will be a boost::function with the same signature as the signal 
     return GetSignal().connect(boost::lambda::bind(callback));   
    } 
    else 
    { 
     typename S::result_type f; 
     return GetSignal().connect((boost::lambda::bind(callback), f)); 
    } 
    } 
} 

我不斷收到編譯錯誤

error: variable or field ‘f’ declared void 
include/boost/function/function_template.hpp:132:42: error: void value not ignored as it ought to be 

由於可以從錯誤中,如果條件與升壓:: is_void可以看出(既不是提高:: is_same)似乎並沒有工作,有誰知道是什麼原因?有沒有更好的方法來做這個綁定?

感謝, 薩克

回答

2

你檢查在運行時這個條件,所以兩個分支需要在編譯時是正確的(他們顯然不是)。 相反,只專注你的模板無效:

// WARNING: untested code! 

template<typename S> 
class signal 
{ 
Connection VoidConnect(boost::function<void(void)> callback) 
    { 
    typename S::result_type f; 
    return GetSignal().connect((boost::lambda::bind(callback), f)); 
    } 
}; 

template<> 
class signal <void> 
{ 
Connection VoidConnect(boost::function<void(void)> callback) 
    { 
    return GetSignal().connect(boost::lambda::bind(callback));   
    } 
}; 

如果你想在成員函數使用enable_if,你應該把它定義爲一個模板。請看下面的代碼:

#include <boost/signals2.hpp> 
#include <boost/utility/enable_if.hpp> 
#include <boost/type_traits/is_void.hpp> 
#include <boost/lambda/bind.hpp> 
#include <boost/lambda/lambda.hpp> 

using namespace boost::signals2; 
class connect 
{ 
public: 
    template<typename S> 
    connection VoidConnect(boost::function<void(void)> callback, S &sig, 
     typename boost::disable_if<boost::is_void<typename S::result_type> >::type *dummy = 0) 
    { 
    typename S::result_type res; 
    return sig.connect((boost::lambda::bind(callback), *res)); 
    } 

    template<typename S> 
    connection VoidConnect(boost::function<void(void)> callback, S &sig, 
     typename boost::enable_if<boost::is_void<typename S::result_type> >::type *dummy = 0) 
    { 
    return sig.connect(boost::lambda::bind(callback));   
    } 

}; 


int main() 
{ 
    boost::function<void(void)> f; 
    signal<void(int)> sig1; 
    connect s1; 
    s1.VoidConnect(f, sig1); 

    signal<int(int)> sig2; 
    connect s2; 
    s2.VoidConnect(f, sig2); 
} 
+0

嗯,感謝您的水溶液和這個模板類信號是具有許多功能一個大班裏,如果專門整個模板無效不是一個選項,有沒有其他的選擇嗎?我目前正在尋找boost :: enable_if是否可用於在編譯時實現選擇。 – Sak 2012-08-07 15:45:37

+0

@Sak,我已經更新了我的答案。 – 2012-08-07 16:42:29

+0

上面的示例工作正常,大多數簽名類型的,但是當信號簽名包含組合如不能編譯:「信號<布爾(浮動),合:: LogicalOrCombiner> SIG3」任何想法,爲什麼? – Sak 2012-08-13 14:02:34