所以我有一个管理资源的类。与std::mutex
类似,它有acquire
和release
方法。要成为一名优秀的RAII风格的程序员,我想将模拟实现为std::unique_lock
,以防止资源被永久获取。但是,出于语义原因,acquire
和release
是const
函数(相信我这一点)。
这意味着我的RAII类的构造函数具有RAIIType( const T &)
的签名。这个问题是,rvalue也会绑定到它。我希望选择SO的大脑来阻止这种情况的发生。
编码方面:
class ResourceType
{
public:
void acquire() const{}
void release() const{}
};
template< class T >
class RAIIClass
{
public:
RAIIClass(const T & in_t) : t(in_t) { t.acquire(); }
~RAIIClass() { t.release(); }
private:
const T & t;
};
ResourceType foo() { return ResourceType(); }
int main()
{
ResourceType x1;
const ResourceType & x2(x1);
{
RAIIClass<ResourceType> x(x1); //Allowable
}
{
RAIIClass<ResourceType> x(x2); //Allowable
}
{
RAIIClass<ResourceType> x(foo()); //Currently allowable, would like to disallow.
}
}
有什么想法吗?
答案 0 :(得分:8)
添加此构造函数:
RAIIClass(const T&&) = delete;
这将绑定到const或非const rvalues,其中const和非const lvalues将更喜欢您现有的构造函数:
RAIIClass(const T & in_t) : t(in_t) { t.acquire(); }
答案 1 :(得分:2)
禁止创建临时管理器的替代方法是更改管理器类,以便在使用临时(Demo at Coliru)调用时在内部存储托管对象:
template< class T >
class RAIIClass;
template <typename T>
RAIIClass<T> make_guard(T&&);
template< class T >
class RAIIClass
{
public:
~RAIIClass() { t.release(); }
private:
friend RAIIClass make_guard<>(T&&);
RAIIClass(T&& in_t) : t(std::forward<T>(in_t)) { t.acquire(); }
T t;
};
template <typename T>
RAIIClass<T> make_guard(T&& t) {
return {std::forward<T>(t)};
}
ResourceType foo() { return {}; }
int main()
{
ResourceType x1;
const ResourceType & x2(x1);
{
auto x = make_guard(x1); //Allowable
}
{
auto x = make_guard(x2); //Allowable
}
{
auto x = make_guard(foo()); //Allowable too.
}
}