2010-11-26 31 views
13

Önişlemcinin nasıl çalıştığına dair zihinsel modelim görünüşte eksiktir ve bu beni çıldırtıyor.Önişlemci jetonu genişletme

İki belirteç birleştirmek istiyorum, ancak ikinci belirteci önce genişletilmelidir. İşte

#define ANSWER 42 

#define FOO foo_ ## ANSWER 

, FOOfoo_ANSWER genişler, ama foo_42 olmak istiyorum. Bu yüzden bu şekilde birleştirme önce argümanlar artıracağı umuduyla bir MERGE makro tanımlamak:

#define MERGE(x, y) x ## y 

#define BAR MERGE(bar_, ANSWER) 

Ama BAR hala bar_ANSWER yerine bar_42 genişler.

#define HELPER(x, y) MERGE(x, y) 

#define BAZ HELPER(baz_, ANSWER) 

Ve şimdi BAZ başarıyla baz_42 şekilde genişletilir: Ben başka makro HELPER tanımlar. Şu anda bu bana sihir gibi geliyor.

Bu davranışı bana açıklayan var mı? Genişleme kuralları tam olarak nasıl çalışır?

+0

Ayrıca, aynı sorunun olası bir yinelenen sorusunu da yaptığımı söylemek isterim. Acaba bu davranış neden açık bir şekilde belgelenmiyor. Önişlemcinin çalıştığı algoritmayı kastediyorum. –

+0

@sandundhammika: Çok açık bir şekilde tanımlanmamış davranış köşeleri olmasına rağmen, 6.10.3. –

cevap

7

sorunuzun here cevabını okuyun:

Sorun şu ki sen makro değiştirme, ön işlemci varken sadece makroları yinelemeli eğer stringizing operatör # ne de jetonu genişleyecektir olduğunu operatörü ## uygulanır. Yani, birleştirme [ref] gerçekleştirirken makro genişletmek etmeyen bir yinelemeli genişletilmiş argüman

+0

Ve bu yüzden BOOST_PP_CAT 'var. –

+0

Yukarıdaki alıntı doğru değil ya da en azından tamamlanmadı. Makroyu genişletmek için, TWO seviyesinin indirgenmesi gerekir (VS2017'de test edilmiş ve Gnu cpp'de aynı raporlar). 2. seviyenin neden gerekli olduğunu açıklamak istiyorum. "#" Veya "##" olmaksızın yalnızca bir düzey indirgeme olması, makroyu genişletmez. Ama 2. seviye var. –

3

Jetonu birleştirme ile belirteç yapıştırma operatörünü kullanabilirsiniz, dolaylama bazı ekstra katmanları kullanmak zorunda .

Bunu aşmak için, bir indirgeme düzeyi kullanırsınız ve birleştirme işleminden önce makroları genişletmek için önişlemciyi alırsınız.

#define STEP1(x, y) STEP2(x, y) // x and y will be expanded before the call to STEP2 
#define STEP2(x, y) x ## y   // x and y will not be expanded, just pasted