3

第 32 週のC++ Guru (プリプロセッサ マクロの「正当な」使用について話す) の最後の例は、DERR_ENTRY実際の実装なしで呼び出されたマクロを示しています。

DERR_ENTRY および関連するマクロの実装は、読者に任されています。

このマクロはこれを置き換えることになっています:

 // For outsiders:
enum Errors {
  ERR_OK = 0,           // No error
  ERR_INVALID_PARAM = 1 // <description>
  ...
}

// For the module's internal use:
map<Error,const char*> lookup;
lookup.insert( make_pair( Error(0), "No error" ) );
lookup.insert( make_pair( Error(1), "<description>" ) );

これで:(はるかに簡単)

DERR_ENTRY( ERR_OK,            0, "No error" ),
DERR_ENTRY( ERR_INVALID_PARAM, 1, "<description>" ),
//...

GotWの著者によると:

実際の情報 (コード/メッセージのペア) を 2 回定義せずに、両方の表現を使用したいと考えています。マクロ マジックを使用すると、次のようにエラーのリストを簡単に記述でき、コンパイル時に適切な構造を作成できます。

しかし、列挙型エントリとマップ エントリの両方を同時に定義する簡単な方法がわかりません。それとも、これを解決できるかわからない未知の構文があるのでしょうか?

では、DERR_ENTRY マクロをどのように実装しますか?

注 : GotW #32 は、プリプロセッサ マクロの能力を示すことになっていることに注意してください。

4

2 に答える 2

3

著者が言及している可能性があるのは、マクロをさまざまな場所でさまざまな意味を持つようにする機能です。この場合、次のことができます。

InternalErrorDefinitions.h (このファイルにはインクルード ガードを含めないでください)。

DERR_ENTRY( ERR_OK,            0, "No error" )
DERR_ENTRY( ERR_INVALID_PARAM, 1, "<description>" )
...

Errors.h (これは、モジュールの外部ユーザーによってインクルードされるファイルです)

#define DERR_ENTRY(err, val, desc) err=val,
enum Errors {
#include "InternalErrorDefinitions.h"
};
#undef DERR_ENTRY

ModuleFile.cpp (モジュールの実装ファイルの 1 つ)

#define DERR_ENTRY(err, val, desc)  lookup.insert( make_pair( Error(val), desc ) );
map<Error,const char*> lookup;
#include "InternalErrorDefinitions.h"
#undef DERR_ENTRY

これにより、エラー定義を 1 か所だけに配置しながら、使用されるさまざまな場所でさまざまな役割を与えることができます。

このプラクティスはX-Macrosと呼ばれます。それらを説明しているこのドブ博士の記事も参照してください。

于 2012-09-03T13:22:57.657 に答える
0
#define DERR_ENTRY(name, value, desc) \
    Error::DefineValue name(desc, value);

の実装はError::DefineValue読者に任されています。

于 2012-09-03T09:18:00.997 に答える