MSVC non espande correttamente __VA_ARGS__

Considera questo codice:

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__ #define G(...) F(__VA_ARGS__) F(1, 2, 3) G(1, 2, 3) 

L’output atteso è X = 1 and VA_ARGS = 2, 3 per entrambe le macro, ed è quello che sto ottenendo con GCC, tuttavia MSVC lo espande come:

 X = 1 and VA_ARGS = 2, 3 X = 1, 2, 3 and VA_ARGS = 

Vale a dire, __VA_ARGS__ è espanso come un singolo argomento, invece di essere suddiviso in più.

In qualche modo intorno a questo?

Il preprocessore di MSVC sembra comportarsi in modo abbastanza diverso dalle specifiche standard.
Probabilmente la seguente soluzione ti aiuterà:

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

Ho pubblicato il seguente problema di supporto Microsoft :

Il seguente programma fornisce errore di compilazione poiché il precompilatore espande __VA_ARGS__ modo errato:

 #include  #define A2(a1, a2) ((a1)+(a2)) #define A_VA(...) A2(__VA_ARGS__) int main(int argc, char *argv[]) { printf("%d\n", A_VA(1, 2)); return 0; } 

Il preprocessore espande printf a: printf (“% d \ n”, ((1, 2) + ()));

invece di printf (“% d \ n”, ((1) + (2)));

Ho ricevuto la seguente risposta insoddisfacente da uno sviluppatore del team di compilatore Microsoft:

Ciao: Il compilatore di Visual C ++ si comporta correttamente in questo caso. Se si combina la regola con cui i token che corrispondono al ‘…’ alla macro invocazione iniziale vengono combinati per formare una singola entity framework (16.3 / p12) con la regola che le sub-macro vengono espanse prima della sostituzione dell’argomento (16.3.1 / p1 ) quindi in questo caso il compilatore ritiene che A2 sia invocato con un singolo argomento: da qui il messaggio di errore.

Quale versione di MSVC stai usando? Avrai bisogno di Visual C ++ 2010.

__VA_ARGS__ stato introdotto per la prima volta da C99. MSVC non ha mai tentato di supportare C99, quindi il supporto non è stato aggiunto.

Ora, tuttavia, __VA_ARGS__ è incluso nel nuovo standard C ++, C ++ 2011 (precedentemente noto come C ++ 0x), che Microsoft apparentemente prevede di supportare, quindi è stato supportato nelle recenti versioni di MSVC.

A proposito, sarà necessario utilizzare un suffisso .cpp nel file sorgente per ottenere questo supporto. MSVC non ha aggiornato il suo frontend C per molto tempo.