Diciamo che ignoreremo cose ovvie come le protezioni per i colpi di testa.
A volte, si desidera generare il codice che deve essere copiato / incollato dal precompilatore:
#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)
che ti consente di codificare questo:
RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;
E può generare messaggi come:
Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"
Si noti che la combinazione di modelli con macro può portare a risultati ancora migliori (ovvero generare automaticamente i valori fianco a fianco con i loro nomi variabili)
Altre volte, per generare informazioni di debug, ad esempio, è necessario __FILE__ e / o __LINE__ di alcuni codici. Di seguito è un classico per Visual C ++:
#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "
Come con il seguente codice:
#pragma message(WRNG "Hello World")
genera messaggi come:
C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World
Altre volte, è necessario generare codice utilizzando gli operatori di concatenazione # e ##, come la generazione di getter e setter per una proprietà (ciò avviene in casi piuttosto limitati, attraverso).
Altre volte, genererai codice che non verrà compilato se utilizzato tramite una funzione, come:
#define MY_TRY try{
#define MY_CATCH } catch(...) {
#define MY_END_TRY }
Quale può essere usato come
MY_TRY
doSomethingDangerous() ;
MY_CATCH
tryToRecoverEvenWithoutMeaningfullInfo() ;
damnThoseMacros() ;
MY_END_TRY
(comunque, ho visto solo questo tipo di codice usato correttamente una volta )
Ultimo, ma non meno importante, il famoso 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;
}
(Nota: copia del codice / incollato dalla home page boost)
Quale è (IMHO) molto meglio di std::for_each
.
Quindi, le macro sono sempre utili perché sono al di fuori delle normali regole del compilatore. Ma trovo che la maggior parte delle volte che ne vedo uno, sono effettivamente resti di codice C mai tradotti in C ++ corretto.