ヘッダー ガードのような明白なものを無視するとしましょう。
場合によっては、プリコンパイラでコピー アンド ペーストする必要があるコードを生成したいことがあります。
#define RAISE_ERROR_STL(p_strMessage) \
do \
{ \
try \
{ \
std::tstringstream strBuffer ; \
strBuffer << p_strMessage ; \
strMessage = strBuffer.str() ; \
raiseSomeAlert(__FILE__, __FUNCSIG__, __LINE__, strBuffer.str().c_str()) \
} \
catch(...){} \
{ \
} \
} \
while(false)
これにより、次のようにコーディングできます。
RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;
次のようなメッセージを生成できます。
Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"
テンプレートとマクロを組み合わせると、さらに良い結果が得られることに注意してください (つまり、変数名と並べて値を自動的に生成します)。
また、たとえばデバッグ情報を生成するために、一部のコードの __FILE__ や __LINE__ が必要になる場合もあります。以下は、Visual C++ の古典です。
#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "
次のコードと同様:
#pragma message(WRNG "Hello World")
次のようなメッセージが生成されます。
C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World
また、プロパティの getter と setter を生成するなど、# および ## 連結演算子を使用してコードを生成する必要がある場合もあります (これは非常に限られたケースです)。
また、次のように、関数を介して使用するとコンパイルされないコードを生成する場合もあります。
#define MY_TRY try{
#define MY_CATCH } catch(...) {
#define MY_END_TRY }
として使用できる
MY_TRY
doSomethingDangerous() ;
MY_CATCH
tryToRecoverEvenWithoutMeaningfullInfo() ;
damnThoseMacros() ;
MY_END_TRY
(それでも、この種のコードが正しく使用されているのを見たのは一度だけです)
最後になりましたが、有名なboost::foreach
!!!
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
}
return 0;
}
(注:boostホームページからのコードのコピー/貼り付け)
これは(IMHO)よりもはるかに優れていstd::for_each
ます。
したがって、マクロは通常のコンパイラ規則の範囲外であるため、常に役立ちます。しかし、ほとんどの場合、それらは適切な C++ に変換されていない C コードの実質的な残骸であることがわかります。