C++11 防止创建临时对象

C++11 防止创建临时对象,c++11,c++14,C++11,C++14,我有一个五年前在这里被问到的问题: 我再次问这个问题的原因是,我对C++11和C++14技术特别感兴趣,这些技术可以防止临时表的构造 一个想法是使用“此*的右值引用”: class ScopedLock { 公众: void enable()&&=delete; void enable()& { 是否启用=真; } ~ScopedLock() { 如果(!已启用){ std::cerr这里是两个伟大答案的C++11版本。我不应该为此获得太多的赞扬,因此考虑投票支持原始答案 用户1773602的

我有一个五年前在这里被问到的问题:

我再次问这个问题的原因是,我对C++11和C++14技术特别感兴趣,这些技术可以防止临时表的构造

一个想法是使用“此*的右值引用”:

class ScopedLock
{
公众:
void enable()&&=delete;
void enable()&
{
是否启用=真;
}
~ScopedLock()
{
如果(!已启用){

std::cerr这里是两个伟大答案的C++11版本。我不应该为此获得太多的赞扬,因此考虑投票支持原始答案

用户1773602的

其思想是定义一个与类同名的已删除函数:

class ScopedLock {
    // ...  
};

void ScopedLock(...) = delete;
这种用法不常见,可能(非常?)不方便:

  class ScopedLock a; // OK             :-| but requires keyword 'class'
  ScopedLock b;       // Compiler error :-(
  ScopedLock();       // Compiler error :-)

如果您不介意出现运行时错误(像OP一样)而不是编译时错误,那么您可以试试这个

基本思想是,与
ScopedLock
构造函数的参数的临时绑定将在
ScopedLock
对象之前或之后销毁,具体取决于后者是否为临时绑定

class ScopedLock {

  bool flag_ = true;

  struct Flag {
    bool* flag;
    ~Flag() {
      *flag = false;
    }
  };

public:

  ScopedLock(Flag&& f = Flag()) {
    f.flag = &flag_;
  }

  ~ScopedLock() {
    if (flag_) {
      std::cerr << "ScopedLock misuse\n.";
      std::terminate();
    }
  }

};

如果编写
void enable()&&=delete;
,实际上会阻止
ScopedLock().enable();
之类的事情进行编译。但是,它不会阻止
ScopedLock()的编译
来自编译。很好的观点。肯定是一个改进。如果有可能向析构函数添加一个右值引用限定符,这个问题就会得到解决。但据我所知,这是不可能的。
templatetypename std::detaction::type&as_左值(T&&T){return T;}
然后
as_左值(ScopedLock{}).enable()
--因此上述方法不起作用。作为XY问题,您可以将锁与锁定的数据组合在一起。仅通过lock类的实例提供对数据的访问。
class ScopedLock {

  bool flag_ = true;

  struct Flag {
    bool* flag;
    ~Flag() {
      *flag = false;
    }
  };

public:

  ScopedLock(Flag&& f = Flag()) {
    f.flag = &flag_;
  }

  ~ScopedLock() {
    if (flag_) {
      std::cerr << "ScopedLock misuse\n.";
      std::terminate();
    }
  }

};
ScopedLock a; // OK
ScopedLock(); // Runtime error