マクロがクラスを定義し、同時にマクロを複数回呼び出してもクラス再定義エラーが発生しないように、マクロを実装するために使用できるC ++のメカニズムはありますか?ありがとう!
2 に答える
マクロは C++ プリプロセッサ ディレクティブを生成できないため、マクロの定義で#define
if が再生成されないように保護する を生成する方法はありません。どういうわけか、別のプリプロセッサ コントロールで処理する必要があります。
#define CLASS_GENERATOR_MACRO(x, y, z) ...defines class x with attributes y, z...
#ifndef GENERATED_CLASS_A
#define GENERATED_CLASS_A
CLASS_GENERATOR_MACRO(a, int, vector<std::string>);
#endif /* GENERATED_CLASS_A */
ただし、CLASS_GENERATOR_MACRO
class を作成するために を 1 回だけ使用することを自動的に強制するものはありませんa
。つまり、ファイルには次のものも含めることができます。
CLASS_GENERATOR_MACRO(a, double, double);
コンパイラは、クラスの再定義について文句を言います (両方が同じスコープにある場合)。
マクロは の呼び出しを生成できます_Pragma
。あなたのシステムが役立つプラグマを提供している可能性はあります。しかし、ほとんどの場合、プラグマを使用した移植可能なソリューションはありません。
このソリューションでは、マクロを使用するたびに新しいクラスをインスタンス化することが望ましい動作であると想定していますが、名前は異なります。
__LINE__
マクロの使用とプリプロセッサのトークン貼り付け演算子##
を組み合わせて、マクロのインスタンス化中に一意のトークンを生成することができます。
#define LOCAL_CLASS(_Base) class _Base ## __LINE__ { /* class definition */ }
これは、次のように使用できます。
LOCAL_CLASS(SomeBase);
LOCAL_CLASS(SomeBase);
これにより、次のコードが生成されます (マクロがソース ファイルの 2 行目と 3 行目でインスタンス化されていると仮定します。
class SomeBase2 { /* class definition */ };
class SomeBase3 { /* class definition */ };
このソリューションの欠点は、生成されたクラスの名前がファイル内の宣言されている場所に応じて変わるため、信頼できないことです。これは、たとえば、クラスがマクロのユーザーによって消費されることを意図していない場合、問題にはなりません。クラスは、マクロによって外部ライブラリに自動的に登録される情報を保持しています。