2009-12-10 3 views
9

のマクロ展開を回避することは、このようなものです:CPP:私は(ログ記録の目的のために)やってみたいどのようなマクロ関数のパラメータ

このコードは私の問題を表示するように書かれている、実際のコードが複雑で、はい私も、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は、マクロの文字列化を書き込み既に展開しているd(「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を呼び出すために使用され、そのないマクロはその呼び出しの前拡張)

トリックを使用せずにこの同じ動作を取得するにはいくつかの方法がありますか?

答えて

7

私がやっている:あなたは何ができるか、しかし、それはその場所にunpeelするために、マクロの層を追加で出力し

#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 ++では動作しません。


EDIT:それはあなたが可変引数マクロを乱用することができ++の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 
FOOBAR 
+0

GCCのプリプロセッサ(存在しない '#include 'を削除する)を使用すると、stdoutに正しいプログラムが得られますが、stderrにはエラーメッセージが出ます。 t.c:11:1:error:貼り付け "、" "BAR"が有効な前処理トークンを与えていない –

+0

gcc/g ++で動作しない –

+0

"うまくいかない"というのは少し強いです。私は 'gcc -E t.c'を実行したときにstdout上でコンパイル可能なプログラムを手に入れました。 –

0

私はあなたができるとは思わない。

#define WRAP(x) x 
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE WRAP(str)) 
+1

BOOST_PP_IDENTITY(X) – KitsuneYMG

+0

@kts Ooh、whaddya know。私は何かを考え、Boostの棺は私の前にwaaaaaayです。 –

+0

WRAPまたは_IDENTITYはどちらも動作しません。(少なくともCPPでは)WRAP()を使用してLOG_ERROR_SIMPLEをパラメータとして呼び出すため、名前の内部には何が入っていますが、展開されません。 – conejoroy

0

あなたはほとんどそれを持っていた

FOO 
BAR 
FOO2 

ながら、gccのプリントを出力します。';' gccの上

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

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

this->log ("ERROR " "at file #a, line #l, function #f: " "some error" " at library " "LIB_OTHER");

私も末尾を削除します

得あなたのコードは次のようになりますように、あなたのマクロから:あなたのcppマクロで展開libにエイリアス(すなわち「1」&「2」)を必要としない場合は
LOG_ERROR(this, LIB_OTHER, "some error");

+0

私はOPが議論の引用を避けたいと思っています。 "LIB_OTHER"が彼とうまくいれば、私は彼が最初に尋ねたwoudld'ntだと思う。 –

+0

libをカンマで貼り付けるとこのエラーが出る:pasting "、" LIB_OTHER "は有効な前処理トークンを与えない。いくつかの "ニュートラル"なキャラクターか隠された空のパラメーターがあります。私はlibを "何か空"で、エラーなしで貼り付けるのに使えますか? – conejoroy

+0

申し訳ありません。私はあなたのニーズを誤解しました。 BOOST_PP_EMPTYは、何も展開しないマクロです。あなたは/ ** /(マークダウンがそれを殺す場合には空のCスタイルのコメントです)を試すこともできます – KitsuneYMG

4

、あなたはまた、代わりに列挙型を使用することができます定義された値の

+2

私はマクロ展開の問題を解決するのが好きでしたが、私はその要素の1つを再考させました。マクロ定数を列挙型に変更しましたが、名前がマクロを展開しないため(マクロではないため)、問題は解決されませんが、それはなくなりました。 – conejoroy

+0

今でも解決したいと思いますが私のプログラムまでは、あなたの提案のおかげで、私はする必要はありません.. – conejoroy

関連する問題