2015-09-04 15 views
6

znalazłem pytanie pokazujący jak przeciążenie makra na podstawie liczby argumentów: Overloading Macro on Number of Arguments__VA_ARGS__ ekspansja użyciu MSVC

Ale jak to mówią, nie jest wykonywana przy użyciu MSVC ponieważ MSVC rozszerza __VA_ARGS__ w jeden żeton zamiast lista argumentów (arg1, arg2, arg3).

Wskazują na inne pytanie, na które zwrócono uwagę: MSVC doesn't expand __VA_ARGS__ correctly Ale nie zostało to w ogóle wyjaśnione, więc nie mogę go dostosować do mojej własnej sprawy, ponieważ nie mogę tego zrozumieć.

Proszę wyjaśnić, jak działa to obejście problemu?

+0

Myślę, że połączony wpis jest nieprawidłowy. Myślę, że właściwym rozwiązaniem jest 'G (...) F (EXPAND (__ VA_ARGS__))' – LPs

+0

@LPs, też tak myślałem, ale spróbuj. –

+0

@JohnBollinger Jestem zbyt Linux wewnątrz, aby umieścić moje ręce na MSVC :). Poważnie, nie mam MSVC, żeby to przetestować. Niech OP wypróbuje to. – LPs

Odpowiedz

9

Rozwiązaniem w pytanie jest takie:

#define EXPAND(x) x 
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__ 
#define G(...) EXPAND(F(__VA_ARGS__)) 

Chodzi o to, że biorąc pod uwagę istniejący zmiennej liczbie argumentów makro F():

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__ 

zamiast pisać żądany zmiennej liczbie argumentów otoki makro jak w tym przypadku, ...

#define G(...) F(__VA_ARGS__) 

... piszesz G() z użyciem dodatkowego makra EXPAND(). Rzeczywista definicja F() nie jest punktem, a w szczególności nie ma znaczenia dla tego przykładu, że makro ekspansja nie tworzy poprawnego kodu C. Jego celem jest wykazanie zachowania preprocesora w odniesieniu do argumentów makr. W szczególności pokazuje to, że chociaż MSVC rozszerza __VA_ARGS__ na pojedynczy token w makrze wariadowym, można go obejść wymuszając podwójne rozszerzenie.

Na przykład, zgodnie z definicją obejścia preprocesor najpierw rozszerza ...

G(1, 2, 3) 

... do ...

EXPAND(F(1, 2, 3)) 

... gdzie 1, 2, 3 jest traktowany jako pojedynczy token. Tokenizacja nie ma już znaczenia, gdy preprocesor przeskanuje dodatkowe zamienniki, jednak widzi 1, 2, 3 jako oddzielne argumenty dla makra F() i rozwija je zgodnie z życzeniem, aby wytworzyć argument dla makra EXPAND(), który po prostu zamienia go na siebie.

Jeśli uważasz, że to działa dziwnie, ale wersja bez EXPAND() nie działa (w MSVC), masz rację.

+0

dzięki za pomoc! przyjrzę się temu później! – Virus721

+0

Działa, dzięki. Teraz lepiej to rozumiem. Wywołanie makra, w którym argumenty mają zostać rozwinięte przy użyciu innego makra, powoduje, że kompilator poprawnie rozwija argumenty. – Virus721

+0

W rzeczywistości mój przypadek jest trochę inny. Chciałbym przeciążać w oparciu o liczbę argumentów: 1 arg -> metoda dla 1 arg, 2 args -> metoda dla 2 argumentów. ALE: Chciałbym również, aby> 2 args -> metoda dla 2 args + va args, ponieważ dwa przeciążenia dla mojego makra mogą mieć listę arg po ich obowiązkowych parametrach. Powoduje to problem, ponieważ gdy wywołuję moją metodę z> 2 argumentami, wówczas jako nazwa metody użyto trzeciego argumentu, który jest nieprawidłowy. – Virus721

Powiązane problemy