Makra z wielokropkiem

2008-08-14 8:24

Chociaż nie jest zalecane, w C++ (podobnie jak w jego poprzedniku, C) możliwe jest wciąż tworzenie funkcji z nieokreśloną liczbą argumentów. Najbardziej znanym przykładem jest oczywiście printf:

  1. void printf(const char*, ...);

Nie wszyscy wiedzą jednak, że zmienną liczbą parametrów mogą mieć też makra (co nazywa się po angielsku variadic macros). Deklaruje się je wtedy w bardzo podobny sposób jak funkcje, też używając wielokropka:

  1. #define LOG(fmt, ...) fprintf(Logger::GetFile(), fmt, __VA_ARGS__);

Żeby jednak dostać się do ‘listy argumentów’ makra, używamy specjalnego identyfikatora __VA_ARGS__. W jego miejsce zostaną podstawione wszystkie podane parametry (z wyjątkiem pierwszego), oddzielone przecinkami tak, jak w oryginalnym “wywołaniu” makra.

Do czego może się to przydać? Jak widać powyżej, za pomocą takich makr możemy na przykład opakowywać wywołania funkcji ze zmienną liczbą argumentów – jak w powyższym przykładzie z logowaniem. Prawdopodobnie mogą być one przydatne także w implementacji jakiejś formy delegatów w C++, zwłaszcza jeśli chodzi o sposób ich wywoływania. Istnieje też ciekawa technika, pozwalająca na tworzenie (w C99 i późniejszych wersjach C/C++) funkcji z nieokreśloną liczbą argumentów, ale z zachowaną kontrolą ich typów.

Be Sociable, Share!
Be Sociable, Share!
Tags:
Author: Xion, posted under Programming »


8 comments for post “Makra z wielokropkiem”.
  1. spaxio:
    August 14th, 2008 o 11:38

    Po co marka skoro doskonale sie do tego nadaja funkcje iniline. Po co wielokoropek skoro doskonale sie do tego nadaje std::vector.

  2. Xion:
    August 14th, 2008 o 21:42

    Bo korzystanie z nietypowych narzędzi językowych daje twojej aplikacji +10 do Szpanu ;P

  3. noisy:
    August 14th, 2008 o 22:33

    bo są takie divice’y na których takie rozwiązanie będzie lepsze, ponieważ niektóre części języka mogą nie być wpełni dobrze (efektywnie) zaimplementowane w pewnych kompilatorach :)

  4. Reg:
    August 17th, 2008 o 11:40

    Dobre to jest! Nie znałem tego. Czy to jest możliwość C++, czy rozszerzenie Microsoftu?

  5. Xion:
    August 17th, 2008 o 23:21

    Tak, to jest część standardu C99, więc i C++ też. Obsługa tego słowa różni się jednak trochę między kompilatorami. Dotyczy to głównie sytuacji, gdy pod __VA_ARGS__ nie daje się podstawić żadnego argumentu i w rozwinięciu makra może zostać przecinek, powodujący błąd składniowy. W VC++ jest on wtedy automatycznie usuwany; w GCC trzeba użyć ## między przecinkiem a __VA_ARGS__.

  6. Misiu:
    August 24th, 2008 o 17:39
    1. #define FINAL_CLASS(className, ...) \
    2.     template <typename T> \
    3.     class className##_is_a_final_class { \
    4.         friend T; \
    5.     private: \
    6.         className##_is_a_final_class() {} \
    7.     }; \
    8.     class className : public virtual className##_is_a_final_class, __VA_ARGS__
    9.  
    10. class Donkey {};
    11. class Horse {};
    12.  
    13. FINAL_CLASS(Mule, public Donkey, public Horse) {
    14. public:
    15.     Mule() {};
    16. };
    17.  
    18.  
    19. class Offspring : public Mule {};
    20.  
    21. Offspring offspring; // ERROR
    22.  
    23. // :)
  7. Misiu:
    August 24th, 2008 o 17:41

    Uuu ostre nawiasy zostały obcięte. :)

    // (by Xion) – poprawione :)

  8. Mandroid:
    March 19th, 2009 o 16:26

    Przykład Miśka zawiera friend T w deklaracji klasy co nie jest standardowym C++.

Comments are disabled.
 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.