2014-05-06 84 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