4

これは可能ですか?クラスの機能の一部を簡単に使用できるようにするマクロを作成したいと考えています。

クラスに setup() と cleanup() という 2 つのメンバー関数があるとします。setup() は、独自のスコープで実行する必要がある操作のパラメーターを設定し、cleanup() はクリーンアップを実行します (コンストラクターに似ています)。およびデストラクタの概念)。

現在、私はこれを行います:

myClassInstance.setup(); //call the setup function
{ //start scope
    //CREATE LOCAL VARS
    //DO STUFF IN THIS SCOPE
    myClassInstance.cleanup(); //cleanup
} //end scope, destroy locals

しかし、代わりに次のようなことをしたいと思います:

NEWSCOPE(myClassInstance) //calls setup()
{
    //CREATE LOCAL VARS
    //DO STUFF IN THIS SCOPE
} // calls cleanup() and destroys locals

私の考えは、マクロが使用され、 setup() と cleanup() がコンストラクタ/デストラクタで実装できるときにインスタンス化できるマクロクラスを作成することでした...またはそのようなもの...

これはこれについて考える正しい方法ですか、それともユーザーが記述したコードを本質的にラップできるマクロを記述する別の方法はありますか?

* 編集 * 関数名が混乱を招いていたため、命名規則を修正しました。

4

4 に答える 4

3

新しいスコープを作成するには、無名ブロックを使用するだけです。

{ 
    Obj obj;
    /* 
    teh codez
    */
}//obj is deallocated

だからマクロはいらない

また、あなたのように聞こえ、startScope実際endScopeにはコンストラクタとデストラクタである必要がありますが、実際に何をしているのかを知らずに知るのは難しいです

更新:私はあなたに答えようとしましたが、代わりに私はただ怒鳴ります.

コンストラクタとデストラクタの概念に似ています

コンストラクタとデストラクタのように聞こえますが、コンストラクタとデストラクタでセットアップとクリーンアップを行うと、操作は自然に実行され、RAII で読みやすくなります。

もう1つのことは、あなたの最初の解決策(私が誤ってあなたに返したもの)が機能しているとあなたは言います.C++が提供する機能(テンプレートやオブジェクトなど)をシミュレートするためにCマクロでマクロを使用した回避策が必要だった理由です. ほとんどすべての状況で、特に C++11 では、マクロは事態を悪化させ、デバッグを困難にするだけです。また、あなたの場合、マクロを実行するときに実際にもっと入力する必要があるように見えますか?

私の提案は、マクロが必要な理由setupcleanup、コンストラクターおよびデストラクタになれない理由を再考することです。

于 2013-08-14T23:25:02.347 に答える
2

これは、RAII でミューテックス ロックを取得するのと同じように扱うことができます。このようなもの:

class MyClassScopeBlock
{
  public:
    MyClassScopeBlock( MyClass & c )
        : obj(c)
    {
        obj.startScope();
    }

    ~MyClassScopeBlock()
    {
        obj.endScope();
    }

  private:
    MyClass & obj;
};

次に、それをスコープ ブロック内のローカル変数としてインスタンス化します。

{
    MyClassScopeBlock block( myClassInstance );
    //CREATE LOCAL VARS
    //DO STUFF IN THIS SCOPE
}

本当に必要な場合は、マクロを定義して、スコープ ブロック内で使用することができます。

#define NEWSCOPE(inst) MyClassScopeBlock block(inst)

個人的には、マクロはできるだけ避けたいと思っています。

于 2013-08-14T23:29:20.153 に答える
0

スコープ全体をマクロ置換内に配置する代わりに、finallyblockのようなものを使用することをお勧めします。これらのマクロを使用して、リンクされたソリューションをカプセル化することに成功しました。

#define FINALLY_NAMED( NAME, ... ) auto && NAME = \
        util::finally( [&]() noexcept { __VA_ARGS__ } );
#define FINALLY( ... ) CPLUS_FINALLY_NAMED( guard, __VA_ARGS__ )
#define DO_FINALLY static_cast< void >( guard );

利用方法:

{
    myClassInstance.setup(); //call the setup function
    FINALLY ( myClassInstance.cleanup(); ) //call the cleanup function before exit

    // do something

    DO_FINALLY // Explicitly note that cleanup happens here. (Only a note.)
}

これは例外セーフであり、コンストラクター/デストラクターのペアと同様に、正常に完了したcleanup場合にのみ実行されます。setupただし、cleanup例外をスローしてはなりません。


しかし、昔ながらの方法でやりたい場合は…</p>

可変長マクロを使用して、マクロ内にスコープ全体を含めることができます。

#define NEWSCOPE( INSTANCE, ... ) { \
    (INSTANCE).setup(); /* call the setup function */ \
    { __VA_ARGS__ } /* paste teh codez here */ \
    (INSTANCE).cleanup(); /* call the cleanup function */

cleanupスコープのポイントは宣言と名前を含めることですがINSTANCE、外部スコープの名前を使用したいため、内部スコープ内に配置しないことをお勧めします。

利用方法:

NEWSCOPE ( myClassInstance,
    // Do stuff.
    // Multiple declarations, anything can go here as if inside braces.
    // (But no #define directives. Down, boy.)
)
于 2013-08-15T00:14:08.300 に答える