Disons que nous ignorerons les choses évidentes comme les gardes d'en-tête.
Parfois, vous souhaitez générer du code qui doit être copié / collé par le précompilateur:
#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)
ce qui vous permet de coder ceci:
RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;
Et peut générer des messages comme:
Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"
Notez que mélanger des modèles avec des macros peut conduire à des résultats encore meilleurs (c'est-à-dire générer automatiquement les valeurs côte à côte avec leurs noms de variables)
D'autres fois, vous avez besoin du __FILE__ et / ou du __LINE__ d'un code, pour générer des informations de débogage, par exemple. Ce qui suit est un classique pour Visual C ++:
#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "
Comme avec le code suivant:
#pragma message(WRNG "Hello World")
il génère des messages comme:
C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World
D'autres fois, vous devez générer du code en utilisant les opérateurs de concaténation # et ##, comme générer des getters et des setters pour une propriété (c'est pour un cas assez limité, à travers).
D'autres fois, vous générerez du code qui ne sera pas compilé s'il est utilisé via une fonction, comme:
#define MY_TRY try{
#define MY_CATCH } catch(...) {
#define MY_END_TRY }
Qui peut être utilisé comme
MY_TRY
doSomethingDangerous() ;
MY_CATCH
tryToRecoverEvenWithoutMeaningfullInfo() ;
damnThoseMacros() ;
MY_END_TRY
(encore, je n'ai vu ce genre de code correctement utilisé qu'une seule fois )
Dernier point, mais non le moindre, le fameux 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;
}
(Remarque: code copié / collé à partir de la page d'accueil Boost)
Ce qui est (à mon humble avis) bien meilleur que std::for_each
.
Ainsi, les macros sont toujours utiles car elles sont en dehors des règles normales du compilateur. Mais je trouve que la plupart du temps j'en vois un, ce sont en fait des restes de code C jamais traduit en C ++ approprié.