10

私がやりたいこと(ログの目的で)は次のようなものです:

このコードは私の問題を示すために書かれています。実際のコードは複雑です。はい、C++ でもマクロを使用する十分な理由があります =)

# define LIB_SOME 1
# define LIB_OTHER 2

# define WHERE "at file #a, line #l, function #f: "
// (look for syntax hightlighting error at SO xd)
# define LOG_ERROR_SIMPLE(ptr, lib, str) ptr->log ("ERROR " str \
                                                   " at library " #lib);
# define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE str)

LOG_ERROR_SIMPLE (this, LIB_SOME, "doing something")
LOG_ERROR (this, LIB_OTHER, "doing something else")

LOG_ERROR_SIMPLE()lib パラメーター (" " で囲まれたマクロ名) の文字列化を書き込みます。

ただし、LOG_ERROR既に展開されているマクロの文字列化 ("2") を書き込みます。lib は展開して呼び出す前に展開されているため、これは予期されたものLOG_ERROR_SIMPLEです。しかし、これは私が必要とするものではありません。

基本的に私の質問は次のとおりです。別のマクロ関数を呼び出すときに、マクロ関数パラメーターのマクロ展開を回避する方法は?

マクロ展開を回避するために私が使用するトリックがあります。

  LOG_ERROR(ptr, lib, str, x) LOG_ERROR_SIMPLE(ptr, x##lib, WHERE str)

  LOG_ERROR(this, LIB_OTHER, "some error",)

(x と lib を貼り付けると生成LIB_OTHERされ、この値は を呼び出すために使用されますLOG_ERROR_SIMPLE。その呼び出しの前に展開されたマクロではありません)

トリックを使用せずにこれと同じ動作を取得する方法はありますか?

4

4 に答える 4

9

私がやっている:

#include <cstdio>

#define FOO 1
#define BAR 2

#define LOG_SIMPLE(ptr, lib, str) printf("%s\n", #lib);
#define LOG(ptr, lib, str) LOG_SIMPLE(ptr, ##lib, str)

int main()
{
  LOG_SIMPLE(0, FOO, "some error");
  LOG(0, BAR, "some other error");
}

これは出力します:

FOO
BAR

MSVC2005 では動作しますが、gcc/g++ では動作しません


編集: gcc/g++ で動作させるには、可変長マクロを悪用できます:

#include <stdio.h>

#define FOO 1
#define BAR 2

#define LOG_SIMPLE(ptr, str, lib) printf("%s\n", #lib);
#define LOG(ptr, str, lib, ...) LOG_SIMPLE(ptr, str, lib##__VA_ARGS__)

int main()
{
  LOG_SIMPLE(0, "some error", FOO);
  LOG(0, "some other error", BAR);
  LOG(0, "some other error", FOO, BAR);
}

ただし、パラメータが多すぎるマクロを使用しないように注意してください。MSVC2005 の出力

FOO
BAR
FOO2

gccが出力している間

FOO
BAR
FOOBAR
于 2009-12-10T13:33:21.010 に答える
4

cpp マクロで展開された lib エイリアス (つまり、'1' と '2') が必要ない場合は、定義された値の代わりに列挙型を使用することもできます。

于 2009-12-10T15:39:56.590 に答える
0

あなたはほとんどそれを持っていました。使用する

#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, ##lib, WHERE str)

gcc の
LOG_ERROR(this, LIB_OTHER, "some error")
利回りについて
this->log ("ERROR " "at file #a, line #l, function #f: " "some error" " at library " "LIB_OTHER");

末尾の「;」も削除します マクロから、コードが次のようになるようにします。
LOG_ERROR(this, LIB_OTHER, "some error");

于 2009-12-10T14:11:24.787 に答える
0

私はあなたができるとは思わない。ただし、マクロのレイヤーを追加して、その場所で剥がすことができます。

#define WRAP(x) x
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE WRAP(str))
于 2009-12-10T13:10:44.247 に答える