Скажімо, ми будемо ігнорувати очевидні речі, такі як охоронці заголовків.
Іноді потрібно генерувати код, який потрібно скопіювати / вставити прекомпілятором:
#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
В іншому випадку вам потрібно генерувати код за допомогою операторів конкатенації # та ##, як-от генерування getters та setters для властивості (це досить обмежений випадок).
В іншому випадку ви будете генерувати код, ніж не буде компілюватися, якщо використовується через функцію, наприклад:
#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;
}
(Примітка: копія коду / вставка з домашньої сторінки підвищення)
Який (ІМХО) спосіб краще, ніж std::for_each
.
Отже, макроси завжди корисні, оскільки знаходяться за межами звичайних правил компілятора. Але я вважаю, що більшість випадків, коли я їх бачу, вони фактично залишаються кодом С, який ніколи не переводиться на належний C ++.