Powiedzmy, że zignorujemy oczywiste rzeczy, takie jak osłony nagłówka.
Czasami chcesz wygenerować kod, który musi zostać skopiowany / wklejony przez prekompilator:
#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)
który umożliwia zakodowanie tego:
RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;
I może generować wiadomości takie jak:
Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"
Zwróć uwagę, że mieszanie szablonów z makrami może prowadzić do jeszcze lepszych wyników (tj. Automatyczne generowanie wartości obok ich nazw zmiennych)
Innym razem potrzebujesz __FILE__ i / lub __LINE__ jakiegoś kodu, na przykład do wygenerowania informacji debugowania. Oto klasyczny przykład języka Visual C ++:
#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "
Jak z następującym kodem:
#pragma message(WRNG "Hello World")
generuje komunikaty takie jak:
C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World
Innym razem musisz wygenerować kod za pomocą operatorów konkatenacji # i ##, takich jak generowanie metod pobierających i ustawiających dla właściwości (dotyczy to dość ograniczonych przypadków).
Innym razem wygenerujesz kod, który nie zostanie skompilowany, jeśli zostanie użyty przez funkcję, na przykład:
#define MY_TRY try{
#define MY_CATCH } catch(...) {
#define MY_END_TRY }
Które mogą być używane jako
MY_TRY
doSomethingDangerous() ;
MY_CATCH
tryToRecoverEvenWithoutMeaningfullInfo() ;
damnThoseMacros() ;
MY_END_TRY
(nadal, widziałem tylko ten rodzaj kodu słusznie użyty raz )
Wreszcie słynny 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;
}
(Uwaga: kod skopiowany / wklejony ze strony głównej boost)
Co jest (IMHO) o wiele lepsze niż std::for_each
.
Zatem makra są zawsze przydatne, ponieważ znajdują się poza normalnymi regułami kompilatora. Ale okazuje się, że przez większość czasu są one pozostałościami kodu C, który nigdy nie został przetłumaczony na poprawne C ++.