是否有可能阻止RAII风格的类"匿名"实例化?

Jef*_*den 7 c++ gcc raii icc visual-c++

假设我有一个RAII风格的C++类:

class StateSaver
{
  public:
    StateSaver(int i) { saveState(); }
    ~StateSaver() { restoreState(); }
};
Run Code Online (Sandbox Code Playgroud)

...在我的代码中使用如下:

void Manipulate()
{
  StateSaver save(1);

  // ...do stuff that modifies state
}
Run Code Online (Sandbox Code Playgroud)

......目标是进入一些状态,做一些事情,然后离开那个范围时离开那个状态.有没有办法让这个拼写错误不编译(或警告,或以某种方式抱怨,以便可以注意到错误)?

void Manipulate()
{
  StateSaver(1); // ruh-roh, state saved and immediately restored!

  // ...do stuff that modifies state
}
Run Code Online (Sandbox Code Playgroud)

我不知道C++本身有什么东西可以用来防止这种情况,但这并不意味着它不存在.如果C++中没有任何内容,则可以接受特定于编译器的扩展.我主要对gcc和msvc的任何目标感兴趣(有一天icc,其他编译器的想法欢迎,但不太可能有用)所以任何一个hacks都很有用(当然,抽象为适当的#ifdef'd宏定义) .

Pav*_*aev 10

我不确定在编译时是否可以做任何事情.对于运行时检查,您可以这样做:

struct SaveMatrix
{
    SaveMatrix(const SaveMatrix& that) {
        assert(this == &that);
        glPushMatrix();
    }
    ~SaveMatrix() { glPopMatrix(); }
};
Run Code Online (Sandbox Code Playgroud)

这需要客户写:

SaveMatrix sm(sm);
Run Code Online (Sandbox Code Playgroud)

并且没有办法对临时做同样的事情而不将它绑定到标识符(此时它与自动变量没有区别).

  • 好的,一开始看起来有点奇怪,但可能成为RAII习语的一部分,因为这个问题确实显示了C++/RAII的真正问题.我宁愿稍微发现因为这个而发现我的锁不起作用. (3认同)

sbi*_*sbi 6

SaveMatrix save();也没有定义对象.它声明了一个函数.

你可以做的很少,以防止其他人(或你自己,FTM)做他们想做的其他事情.我唯一能想到的不是编写代码本身,而是编写宏代码.

#define SAVE_MATRIX SaveMatrix save ## __LINE__
Run Code Online (Sandbox Code Playgroud)

但是,这非常难看.OTOH,它确实在编译时捕获错误.


Dav*_*ron 3

实际上,我必须从 Waldo 发布的变体中通过多种方式调整我的解决方案,但我最终得到的是一个宏化版本:

class GuardNotifier
{
    bool* notified;
  public:
    GuardNotifier() : notified(NULL) { }
    void init(bool* ptr) { notified = ptr; }
    ~GuardNotifier() { *notified = true; }
};
class GuardNotifyReceiver
{
    bool notified;
  public:
    GuardNotifyReceiver() : notified(false) { }
    void init(const GuardNotifier& notifier)
      { const_cast<GuardNotifier&>(notifier).init(&notified); }
    ~GuardNotifyReceiver() { assert(notified); }
};
class StateSaver
{
    GuardNotifyReceiver receiver;
  public:
    StateSaver(int i,
               const GuardNotifier& notifier = GuardNotifier())
    {
      receiver.init(notifier)
      saveState();
    }
    ~StateSaver()
    {
      restoreState();
    }
};
Run Code Online (Sandbox Code Playgroud)