Böyle gitmeyecek:
#define COMMA ,
#if defined(DOXYGEN_PROCESSING)
# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
#else
# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
#endif
DOCUMENTED_TYPEDEF(Foo<R COMMA S>,Bar)
Testi: Herhangi ikame gerçekleşmeden önce
$ gcc -E comma-macro.c
# 1 "comma-macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "comma-macro.c"
# 9 "comma-macro.c"
typedef Foo<R , S> Bar;
Makro argümanı listeleri parantez ve virgül için çözümlenir. Sonra COMMA
, x
bağımsız değişkeninde değiştirilir ve x
, makro gövdeye ikame edilir. O zaman, argüman kırma yapılır; COMMA
'un bir virgül punctuator jetonu ile değiştirilmiş olması uygun değildir. Ancak, bu makro o makro tarafından oluşturulan herhangi bir makro çağrısında oluşan bağımsız değişkenler olacaktır, bu yüzden korunmaları gerekiyorsa, daha çılgın bir şey gerekir. Bir fonksiyon benzeri makro arkasında COMMA
gizleyebilirsiniz
, PAIR
ki: İlk bakışta
#define COMMA ,
#define PAIR(A, B) A COMMA B
#if defined(DOXYGEN_PROCESSING)
# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
#else
# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
#endif
DOCUMENTED_TYPEDEF(PAIR(Foo<R, S>), Bar)
daha çekici, ama olumsuzlukları muhtemelen vardır. Daha da şaşırtılmış. Okuyucu merak ediyor, PAIR
'un arkasında semantik var mı? Oysa, COMMA
, anlambilimine sahip olmak için çok geniş görünüyor ve amaç, önişlemciyle savaşmaktan kaynaklanan savaş izleri olan herkes için aniden açık.
PAIR
hakkında, bunu gizleyebilir ve Zwol'un yanıtındaki gibi bir sözdizimi ile sonuçlanabilir.Ama sonra DOCUMENTED_TYPEDEF
'un birden fazla çeşidine ihtiyacımız var. o C99 tarzı variadic makrolarıyla yapılabilir olabilir gibi
#define PAIR(A, B) A, B
#if defined(DOXYGEN_PROCESSING)
# define DOCUMENTED_TYPEDEF_2(x2, y) class y : public PAIR x2 {};
#else
# define DOCUMENTED_TYPEDEF_2(x2, y) typedef PAIR x2 y;
#endif
DOCUMENTED_TYPEDEF_2((<R, S>), Bar)
$ gcc -std=c90 -E -Wall -pedantic comma-macro.c
# 1 "comma-macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "comma-macro.c"
# 11 "comma-macro.c"
typedef <R, S> Bar;
Bu arar:
Ayrıca, bu arada, en bir makro sağ tarafta gerekli değildir yararsız COMMA
bırakalım . Bununla birlikte, bu yorumda tartışılan taşınabilirlik şartını ihlal edebilir, bunun C++ olduğunu belirtmez. gelecek ziyaretçiler uğruna:
#define PNEUMATIC_COMMA_GUN(A, ...) A, ## __VA_ARGS__
#if defined(DOXYGEN_PROCESSING)
# define DOCUMENTED_TYPEDEF(xv, y) class y : public PNEUMATIC_COMMA_GUN xv {};
#else
# define DOCUMENTED_TYPEDEF(xv, y) typedef PNEUMATIC_COMMA_GUN xv y;
#endif
DOCUMENTED_TYPEDEF((<R, S, T, L, N, E>), Bar)
$ gcc -std=c99 -E -Wall -pedantic comma-macro.c
# 1 "comma-macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "comma-macro.c"
# 9 "comma-macro.c"
typedef <R, S, T, L, N, E> Bar;
Ben sol argüman X bir deklarasyon belirtici pozisyonuna konur, çünkü sorunlara neden olur sanıyorum. C ve C++ stili bildirimlerinde, bildirim belirticileri isteğe bağlı parantezleri almaz. Ancak, beyancılar şunları yapar: “int x;” ve “int (x);” aynı şeydir. (int) x; 'cast ifadesine benziyor. – Kaz
@Kaz * Her zaman * ile * P99 değişkenlikli makroları uygulayan yalnızca destekleyici derleyicilerle * ve * şablon parametrelerini içerebilen argümanın etrafına parantez koyar mısınız? Eğer öyleyse, çalışacak bir hack var. – zwol