有一个类模板Foo<T>
。对于某些特定类型,函数应该使用lock_guard
。下面是示例代码:
#include <type_traits>
#include <mutex>
#include <vector>
template<typename T>
class Foo {
public:
void do_something(int k) {
if constexpr(std::is_same_v<T, NeedMutexType>) {
std::lock_guard<std::mutex> lock(mtx_);
}
resource_.push_back(k);
// code for task with resource_ ...
}
private:
std::mutex mtx_;
std::vector<int> resource_;
};
std::lock_guard
将在if constexpr作用域的末尾析构。(如果不是真的,请指正。)
为了处理这个问题,我可以将下面的resource_
任务的代码复制到if constexpr作用域中,或者只使用原始的std::mutex
,如mtx_.lock()
和mtx_.unlock()
。
有没有一些方法可以用std::lock_guard
来处理这个问题?谢谢。
3条答案
按热度按时间muk1a3rh1#
如果您经常需要做这种事情,也许std::conditional可以在这里提供帮助。
这里我们定义了一个什么都不做的类模板,它的构造方式与
std::lock_guard
相同。然后,我们将其与std::conditional
一起使用,根据类型检查的结果选择std::lock_guard
或FakeLockGuard
。现在您可以按如下方式使用它:
您可以通过在
FakeLockGuard
构造函数中设置一个断点或使其输出一些内容来轻松验证这是否有效。这就是如何在编译时使其全部工作。但是我认为,正如您已经提到的,您可以简单地构造一个
unique_lock
,然后有条件地锁定它。这样做的好处是,无论是谁,都可以更清楚地使用您的代码。最后,这取决于你认为最合适的方式。sqserrrh2#
只需在unlocked状态下构造锁,然后稍后锁定它:
请注意,您需要使用
std::unique_lock
,因为std::lock_guard
不能被构造为未锁定b5lpy0ml3#
你基本上有两个不同的功能:
所以你可以把常见的东西打包成一个不同的函数:
if constexpr
创建自己的作用域的一般修复方法是将其放在lambda中:它只是比helper函数的类型少一点,但可能更容易使用(特别是如果您多次使用它并创建成员函数
auto maybe_lock()
)。