Digamos que ignoraremos cosas obvias como los protectores de cabecera.
A veces, desea generar código que el precompilador debe copiar / pegar:
#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)
que le permite codificar esto:
RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;
Y puede generar mensajes como:
Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"
Tenga en cuenta que mezclar plantillas con macros puede conducir a resultados aún mejores (es decir, generar automáticamente los valores lado a lado con sus nombres de variables)
Otras veces, necesita el __FILE__ y / o la __LINE__ de algún código, para generar información de depuración, por ejemplo. El siguiente es un clásico para Visual C ++:
#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "
Como con el siguiente código:
#pragma message(WRNG "Hello World")
genera mensajes como:
C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World
Otras veces, debe generar código utilizando los operadores de concatenación # y ##, como generar captadores y establecedores para una propiedad (esto es para casos bastante limitados, a través de).
Otras veces, generará código que no se compilará si se usa a través de una función, como:
#define MY_TRY try{
#define MY_CATCH } catch(...) {
#define MY_END_TRY }
Que se puede usar como
MY_TRY
doSomethingDangerous() ;
MY_CATCH
tryToRecoverEvenWithoutMeaningfullInfo() ;
damnThoseMacros() ;
MY_END_TRY
(Aún así, solo vi este tipo de código utilizado correctamente una vez )
Por último, pero no menos importante, los famosos 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 de código / pegado desde la página de inicio de boost)
Que es (en mi humilde opinión) mucho mejor que std::for_each
.
Por lo tanto, las macros siempre son útiles porque están fuera de las reglas normales del compilador. Pero encuentro que la mayoría de las veces que veo uno, son efectivamente restos de código C que nunca se traducen a C ++ adecuado.