Mam dwa makra FOO2
i FOO3
:
#define FOO2(x,y) ...
#define FOO3(x,y,z) ...
Chcę zdefiniować nowe makro FOO
w następujący sposób:
#define FOO(x,y) FOO2(x,y)
#define FOO(x,y,z) FOO3(x,y,z)
Ale to nie działa, ponieważ makra nie przeciążają wielu argumentów.
Bez modyfikacji FOO2
i FOO3
czy istnieje jakiś sposób zdefiniowania makra FOO
(przy użyciu __VA_ARGS__
lub w inny sposób), aby uzyskać taki sam efekt wysyłania FOO(x,y)
do FOO2
i FOO(x,y,z)
do FOO3
?
c
macros
c-preprocessor
Andrew Tomazos
źródło
źródło
Odpowiedzi:
Proste jak:
Więc jeśli masz te makra:
Jeśli chcesz czwarty:
Oczywiście, jeśli zdefiniujesz
FOO2
,FOO3
aFOO4
dane wyjściowe zostaną zastąpione danymi z zdefiniowanych makr.źródło
EXPAND
wspomnianego w linku @ Étienne, w zasadzie wywołujesz go w tenGET_MACRO
sposób#define FOO(...) EXPAND(GET_MACRO(__VA_ARGS__, FOO3, FOO2, FOO1)(__VA_ARGS__))
i powinien on rozwinąć się do odpowiedniej liczby argumentów w msvc.ISO C++11 requires at least one argument for the "..." in a variadic macro
. Aby to naprawić, dodaj nieużywany argument (lub nawet przecinek) po ostatnim parametrze w definicji FOO (...):#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2, UNUSED)(__VA_ARGS__)
( Zobacz, jak działa na Coliru ).Aby dodać odpowiedź netcodera , MOŻESZ to zrobić za pomocą makra 0-argumentowego za pomocą
##__VA_ARGS__
rozszerzenia GCC :źródło
#define FOO0 _Pragma("error FOO0 not allowed")
?FOO0
nie działa w qt + mingw32, wywołanieFOO0
wywołaFOO1
-std=c99
lub-std=c11
. Musisz użyć-std=gnu99
lub-std=gnu11
zamiast_0, ##__VA_ARGS__
go_0 __VA_OPT__(,) __VA_ARGS__
to nowy sposób na zrobienie tego.Oto bardziej ogólne rozwiązanie:
Zdefiniuj swoje funkcje:
Teraz możesz używać
FOO
z argumentami 2, 3 i 4:Ograniczenia
Pomysły
Użyj go jako domyślnych argumentów:
Użyj go do funkcji z możliwą nieskończoną liczbą argumentów:
PS:
__NARG__
jest kopiowany z Laurenta Deniau i Rolanda Illiga tutaj: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1źródło
__NARG_I_
wydaje się całkowicie niepotrzebne i zbędne. To tylko dodatkowy krok i zamieszanie. Polecam usuwania go całkowicie i po prostu definiowanie__NARG__
zamiast jak:#define __NARG__(...) __ARG_N(__VA_ARGS__,__RSEQ_N())
._VFUNC_
: po prostu go usuń. Następnie zdefiniuj_VFUNC
jako:#define _VFUNC(name, n) name##n
zamiast#define _VFUNC(name, n) _VFUNC_(name, n)
.Właśnie to badałem i natknąłem się na to tutaj . Autor dodał domyślną obsługę argumentów funkcji C za pomocą makr.
Spróbuję krótko streścić artykuł. Zasadniczo musisz zdefiniować makro, które może liczyć argumenty. To makro zwróci 2, 1, 0 lub dowolny zakres obsługiwanych argumentów. Na przykład:
Dzięki temu musisz utworzyć kolejne makro, które pobierze zmienną liczbę argumentów, zlicza argumenty i wywołuje odpowiednie makro. Wziąłem twoje makro makra i połączyłem je z przykładem artykułu. Mam funkcję wywołania FOO1 a () i funkcję wywołania FOO2 a z argumentem b (oczywiście zakładam, że C ++ tutaj, ale możesz zmienić makro na cokolwiek).
Więc jeśli masz
Preprocesor rozszerza to do
Na pewno przeczytałbym link do tego artykułu. Jest to bardzo pouczające i wspomina, że NARG2 nie będzie działać na pustych argumentach. Śledzi to tutaj .
źródło
Oto bardziej zwarta wersja powyższej odpowiedzi . Z przykładem
Biegać:
Zauważ, że posiadanie obu
_OVR
i_OVR_EXPAND
może wyglądać na zbędne, ale konieczne jest, aby preprocesor rozwinął_COUNT_ARGS(__VA_ARGS__)
część, która w przeciwnym razie jest traktowana jako ciąg.źródło
Być może możesz użyć tego makra, aby policzyć liczbę argumentów .
źródło
Oto część odpowiedzi Evgeni Siergiejewa. Ten obsługuje również zerowe przeciążenia argumentów !
Testowałem to z GCC i MinGW. Powinien współpracować ze starymi i nowymi wersjami C ++. Zauważ, że nie gwarantowałbym tego w przypadku MSVC ... Ale z pewnymi poprawkami, jestem pewien, że można by do tego nadawać.
Sformatowałem to również, aby wkleić do pliku nagłówka (który nazwałem macroutil.h). Jeśli to zrobisz, możesz po prostu dołączyć ten nagłówek, czego potrzebujesz, i nie patrzeć na nieprzyjemności związane z implementacją.
źródło
Wydaje się, że działa to dobrze na GCC, Clang i MSVC. To oczyszczona wersja niektórych odpowiedzi tutaj
źródło
#define func0() foo
? Obecna wersja niestety nie obsługuje tego przypadku.