展開して改行を含む cpp マクロを作成するにはどうすればよいですか?
7 に答える
テンプレートで置き換えることができないコードを合成するために、多くのプリプロセッサ マクロ関数を含む大規模なプロジェクトに取り組んでいます。信じてください、私はあらゆる種類のテンプレートのトリックに精通していますが、コードを直接作成できる標準化されたタイプセーフなメタプログラミング言語がない限り、古き良きプリプロセッサとその面倒なマクロを使い続けていくつかの問題を解決する必要があります.なしでは 10 倍のコードを書く必要があります。一部のマクロは何行にもわたっており、前処理されたコードでは非常に読みにくいものです。したがって、私はその問題の解決策を考えました。私が思いついたのは次のとおりです。
たとえば、MyMacro.hppという名前のファイルに、複数行にわたる C/C++ マクロがあるとします。
// Content of MyMacro.hpp
#include "MultilineMacroDebugging.hpp"
#define PRINT_VARIABLE(S) \
__NL__ std::cout << #S << ": " << S << std::endl; \
__NL__ /* more lines if necessary */ \
__NL__ /* even more lines */
このようなマクロを定義したすべてのファイルに、次の内容を含む別のファイルMultilineMacroDebugging.hppを含めます。
// Content of MultilineMacroDebugging.hpp
#ifndef HAVE_MULTILINE_DEBUGGING
#define __NL__
#endif
これにより空のマクロ__NL__
が__NL__
定義され、前処理中に定義が消えます。マクロは、MyImplementation.cppという名前のファイルなど、どこかで使用できます。
// Content of MyImplementation.cpp
// Uncomment the following line to enable macro debugging
//#define HAVE_MULTILINE_DEBUGGING
#include "MyMacro.hpp"
int a = 10;
PRINT_VARIABLE(a)
マクロをデバッグする必要がある場合は、MyImplementation.cppPRINT_VARIABLE
でマクロを定義している行のコメントを外します。結果として得られるコードはもちろんコンパイルされません。マクロは未定義になるため、コンパイルされたコードに残りますが、前処理することはできます。HAVE_MULTILINE_DEBUGGING
__NL__
重要なステップは__NL__
、お気に入りのテキスト エディタを使用して、プリプロセッサ出力の文字列を改行に置き換えることです。ほら、前処理後に置き換えられたマクロの結果の読み取り可能な表現が得られます。これは、コンパイラが表示するものとまったく同じです。人為的に導入された改行の場合。
それは不可能。ファイルのリストまたはプリプロセッサの出力を見ている場合にのみ関連します。
マクロを読みやすくするための一般的な手法は、\ 文字を使用してマクロを次の行に続けることです。
あなたの利益のために、出力をリストする際に展開されたマクロに新しい行を含めるコンパイラを見たことがあります。これは、展開されたマクロを読んで、コンパイラに実際に何をするように要求したかを理解しようとする私たち貧しい人間にとってのみ役に立ちます。コンパイラに違いはありません。
C および C++ 言語は、文字列の外側にあるすべての空白を同じ方法で扱います。ちょうど区切りとして。
C および C++ コンパイラは引用符で囲まれていない空白を無視するため (> > テンプレートの問題を除く)、マクロに改行を発行させることはあまり意味がありません。マクロの各行をバックスラッシュで終了することにより、マクロを複数の行にまたがらせることができますが、これは改行を出力しません。
Cコンパイラは空白を認識しますが、スペース、タブ、または新しい行を区別しません。
マクロの文字列内に改行を入れるにはどうすればよいですか。
#define SOME_STRING "Some string\n with a new line."
動作します。
ここで何を求めているのかよくわかりません。複数行にマクロが必要ですか?
#define NEWLINE_MACRO(x) line1 \
line2 \
line3
さらに、マクロにリテラルを含めたい場合は、次のようにします。
#define NEWLINE_MACRO(x) ##x
xに入力したものは、## xの代わりに配置されるため、次のようになります。
NEWLINE_MACRO( line1 ) // is replaced with line1
これは、カスタムグローバル関数を作成する場合に役立ち、関数名の一部を変更するだけで済みます。
また:
#define NEWLINE_MACRO(x) #x // stringify x
xを引用符で囲みます
行末に \ を使用します。do...while(0) を使用する多くの C マクロを見てきました。
#define foo() do \
{
//code goes here \
\
\
}while(0);
また、多くの場合に括弧を使用することを忘れないでください。
例:
#define foo(x) a+b
//should be
#define foo(x) (a+b)
\
次のように使用します。
#define my_multiline_macro(a, b, c) \
if (a) { \
b += c; \
}