2017-05-19 55 views
3

我正在嘗試編寫一個類模板,它將在構造函數參數中獲得兩個std::function s,並在構造和銷燬時以RAII樣式調用它們。調用std ::功能

我錯過了什麼?

template <class T> 
class HelloGoodbye{ 
public: 
HelloGoodbye(std::function<T> const & f, std::function<T> const &g) 
    :mf(f),mg(g) 
{ 
    mf(); 
} 


~HelloGoodBye() 
{ 
    mg(); 
} 

private: 
std::function<T> mf; 
std::function<T> mg; 
}; 


class Printer 
{ 
    public: 
    void hello() 
    { 
     std::cout << "hello!" << std::endl; 
    } 
    void goodbye() 
    { 
     std::cout << "Goodbye!" << std::endl; 
    } 
}; 

int main() 
{ 
     Printer p; 
     auto hi = std::bind(&Printer::hello, &p); 
     auto bye = std::bind(&Printer::goodbye, &p); 
     HelloGoodbye hgb(hi,bye);  
} 
+0

你不需要保存'mf'。 – John

回答

3

HelloGoodbye是一個類模板,您在使用它時需要指定模板參數。例如

HelloGoodbye<void()> hgb(hi,bye); 

LIVE

BTW:我想~HelloGoodBye()~HelloGoodbye()一個錯字。

0

可以明確的hgb模板類型,由songyuanyao建議,或者您也可以創建生成功能

template <typename T> 
HelloGoodbye<T> makeHG (std::function<T> const & hi, 
         std::function<T> const & bye) 
{ return { hi, bye }; } 

,並使用auto,可以初始化hgb如下

auto hgb = makeHG(hi, bye); 

不幸的是,std::bind是一個具有未定義返回值的奇怪野獸,因此您無法將從std::bind返回的類型傳遞給makeHG()以獲取T型扣除。

所以,如果你想使用makeHG(),您可以使用auto定義hibye,但你必須顯式類型如下

std::function<void()> hi = std::bind(&Printer::hello, &p); 
    std::function<void()> bye = std::bind(&Printer::goodbye, &p); 

所以,我認爲,在sonyuanyao一個更好的解決方案。

+0

一旦他使用make函數來構建模板類,他不再需要重量級的std :: function。他可以爲可調用類型創建模板並存儲結束的類型。 – John

+0

考慮到'f'和'g'必須可以不帶參數調用,我們可以從'std :: bind'創建函數簽名;假設'std :: is_bind_expression :: value'是'true'和'decltype(std :: declval ()())'是一個有效的類型,那麼提供給'std :: function'的簽名應該是'typename T :: result_type的()'。 [像這樣](http://coliru.stacked-crooked.com/a/89ba8e3b8e14d949)。不過,這可能有些脆弱,我不知道這是否是好的做法。 –

+0

@JustinTime - 謝謝,但是...我想到了這個解決方案(我不認爲它很脆弱),但是,恕我直言,沒有什麼意思。因爲只能在這個特定的(無參數)情況下工作;我搜索了一個更通用的解決方案(這相當於編寫一個模板「make」函數將一個'std :: bind()'返回值轉換爲對應的'std :: function'值,檢測它的類型),但沒有成功。 – max66