C++ 允许l值引用和不允许r值引用作为函数参数?

C++ 允许l值引用和不允许r值引用作为函数参数?,c++,c++11,rvalue-reference,C++,C++11,Rvalue Reference,所以我有一个管理资源的类。与std::mutex类似,它有acquire和release方法。为了成为一名优秀的RAII风格的程序员,我想实现模拟到std::unique_lock,以防止永远获取资源。然而,出于语义上的原因,acquire和release是const函数(相信我) 这意味着我的RAII类的构造函数有一个签名raitype(const T&)。这个问题是,一个右值也会绑定到它。我希望能从苏的脑子里找出一个阻止这种事情发生的方法 在编码方面: class ResourceType

所以我有一个管理资源的类。与
std::mutex
类似,它有
acquire
release
方法。为了成为一名优秀的RAII风格的程序员,我想实现模拟到
std::unique_lock
,以防止永远获取资源。然而,出于语义上的原因,
acquire
release
const
函数(相信我)

这意味着我的RAII类的构造函数有一个签名
raitype(const T&)
。这个问题是,一个右值也会绑定到它。我希望能从苏的脑子里找出一个阻止这种事情发生的方法

在编码方面:

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.
   }
}
类资源类型
{
公众:
void acquire()常量{}
void release()常量{}
};
模板
类RAIIClass
{
公众:
RAIIClass(const T&in_T):T(in_T){T.acquire();}
~RAIIClass(){t.release();}
私人:
康斯特T&T;
};
ResourceType foo(){return ResourceType();}
int main()
{
资源型x1;
常量资源类型&x2(x1);
{
RAIIClass x(x1);//允许
}
{
RAIIClass x(x2);//允许
}
{
RAIIClass x(foo());//当前允许,希望不允许。
}
}
有什么想法吗?

添加此构造函数:

RAIIClass(const T&&) = delete;
RAIIClass(const T & in_t) : t(in_t) { t.acquire(); }
这将绑定到常量或非常量右值,其中常量和非常量左值都将首选现有构造函数:

RAIIClass(const T&&) = delete;
RAIIClass(const T & in_t) : t(in_t) { t.acquire(); }

禁止为临时对象创建管理器的另一种方法是更改管理器类,以便在使用临时()调用时在内部存储托管对象:

模板
类RAIIClass;
模板
RAIIClass make_防护装置(T&&);
模板
类RAIIClass
{
公众:
~RAIIClass(){t.release();}
私人:
朋友拉伊格拉斯(T&&);
RAIIClass(T&&in_T):T(std::forward(in_T)){T.acquire();}
T;
};
模板
RAIIClass make_防护装置(T&T){
返回{std::forward(t)};
}
ResourceType foo(){return{};}
int main()
{
资源型x1;
常量资源类型&x2(x1);
{
auto x=使保护(x1);//允许
}
{
auto x=使保护(x2);//允许
}
{
auto x=make_guard(foo());//也允许。
}
}

为什么要避免右值?另外,请注意,在这种设计中,您的
RaiicClass
是不可分配的(也许这很好,但请注意!)。立即解决方案:
RaiicClass(T&&)=delete
但我不相信这不是xy问题。@juanchopanza由于专有原因,我无法真正了解它,但它们在语义上是常量,内部有一个可变变量。你必须相信我,这在实际问题中是有意义的。@OliverCharlesworth RAIIClass的析构函数会调用一个无效的ref,如果参数是一个临时的Yup,正如上面所建议的,但你似乎是最快实际键入它作为答案的人。谢谢。+1:这里的诀窍是有一个工厂推导的函数,它接受
T&&
,一个构造函数接受
T&&
,然后在实例中存储
T
:这是一种常见模式。如果
T&&
是临时右值,则
T
是值类型,否则它是引用类型。在
RaiicClass
中明确地阻止
操作符=
和复制构造,并明确地允许移动构造,可能是一个好主意。