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:

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:

#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.

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
    #define FINAL_CLASS(className, ...) \
        template <typename T> \
        class className##_is_a_final_class { \
            friend T; \
        private: \
            className##_is_a_final_class() {} \
        }; \
        class className : public virtual className##_is_a_final_class, __VA_ARGS__

    class Donkey {};
    class Horse {};

    FINAL_CLASS(Mule, public Donkey, public Horse) {
    public:
        Mule() {};
    };

    class Offspring : public Mule {};

    Offspring offspring; // ERROR

    // :)

  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++.

Add a comment

Newline tags are added automatically.
For code, use [code][/code]. You can also insert LaTeX formulae inside [tex][/tex].
HTML tags allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 


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