2014-05-06 82 views
2

在我的C++代碼中,有時我需要從某些庫調用C函數。有些時候這些是成對的功能,如鎖定功能,然後是解鎖功能。我想確保我不會忘記調用解鎖功能。所以我正在嘗試編寫一個模板類來處理它,但我無法做到。如何選擇函數指針類型?

template <class T> 
class CInReleaser 
{ 
public: 
    CInReleaser(T func) : _func(func) {} 
    ~CInReleaser() { _func();} 
    T _func; 
}; 

void somefunc() 
{ 
    DATA something; 
    // call locking function 
    lock_something(something); 
    CInReleaser<XXX> release(boost::bind(unlock_something,something)); 
    . 
    . 
} 

當somefunc()函數結束時,函數unlock_something()應該被調用。但是我無法預測類型XXX。我怎樣才能得到這個編譯?在代碼

template<typename T> 
CInReleaser<T> makeReleaser(T func) { 
    return CInReleaser<T>(func); 
} 

再後來:

+2

最好在構造函數中進行鎖定並在析構函數中進行解鎖。然後實例化一個單一的防護對象。 – juanchopanza

+0

鎖定不會總是在相同的範圍內發生。但在構造函數中鎖定並不能解決我的問題。 – Sharath

+0

你到目前爲止試過的是什麼,而不是XXX?你收到了哪些錯誤信息? – TobiMcNamobi

回答

1

創建包裝工廠函數利用函數模板參數推導

auto release = makeReleaser(boost::bind(unlock_something,something)); 
+0

賓果!就是這個。我想要一個簡單的方法來預測類型,因爲每次採用不同的參數時函數可能會有所不同。非常感謝你。 – Sharath

1

創建鎖定在構造函數和析構函數解鎖類。

template <class Lock, class Unlock> 
struct CInReleaser 
{ 
    CInReleaser(Lock lock, Unlock unlock) : _lock(lock), _unlock(unlock) 
    { 
     _lock(); 
    } 
    ~CInReleaser() 
    { 
     _unlock(); 
    } 
}; 

創建一個函數來幫助構造類的語法。

template <class Lock, class Unlock> 
CInReleaser<Lock, Unlock> makeCInReleaser(Lock lock, Unlock unlock) 
{ 
    return CInReleaser<Lock, Unlock>(lock, unlock); 
} 

示例用法。

void somefunc() 
{ 
    auto releaser = makeCInReleaser(boost::bind(lock_something, something), 
            boost::bind(unlock_something, something)); 
} 
+0

鎖定和解鎖功能可能不在相同的範圍內。所以這不會。另外,我需要將參數傳遞給函數,因此綁定是必需的。看看接受的答案,它解決了這兩個要求。 – Sharath

+0

@SharathKShetty好點。我更新了我的答案以解決它們。 –

1

,如果您有可用的C++ 11的支持,我只想建議使用小幫手像

class Guard 
{ 
public: 
    Guard(std::function<void()> fn) : fn_(std::move(fn)) {} 
    ~Guard() { if(fn_) fn_(); } 
private: 
    std::function<void()> fn_; 
}; 

,然後你可以只用一點點lambda來寫這樣的

void somefunc() 
{ 
    DATA something; 
    // call locking function 
    lock_something(something); 
    Guard g([=](){ something->unlock_something(); }); 
    . 
    . 
} 
+0

有趣的使用lambda功能。不知道我完全理解,但我會嘗試看看。可能有用的知道。 – Sharath

+0

Guard類實際做的是接受任何沒有參數並返回void的函數。你也可以傳遞一個全局函數,但在這個例子中,我只傳入了一個完全類型的lambda(沒有參數,返回void)。當範圍退出時,現在只需要在lambda中聲明該操作(這裏我只是在某個對象上調用了unlock_something(),但是可以將所有內容都放在那裏)。 –

+0

那部分很清楚。我不確定std :: move()是右值引用。儘管我已經閱讀過它,但直到現在我才真正使用它。 – Sharath