2011-12-21 32 views
8

Bir mühendislik spesifikasyon belgesindeki elemanlarla aynı şekilde adlandırılan birçok değişken var, bu yüzden ismin dize versiyonu da kullanışlıdır.C/C++ macro argüman olarak genişletiliyor, argüman olarak argüman

#define MACRO(a) a, #a 

Tipik kullanım şöyledir::

void someFunction(int a, const char *name); 

someFunction(MACRO(meaningfully_named_variable)); 

sorum üç bölümden oluşmaktadır:

  • daha iyi bir yolu var mı

    Kendimi böyle çok makro kullanarak bulmak Bunu yapıyor?

  • Benzer bir makro, Boost veya diğer kütüphanelerde kullanılabilir mi?
  • Değilse, açık ve kullanışlı hale getirmek için bunu nasıl geliştirebilir ve yeniden adlandırabilirim?

düzenleme yukarıda az bir örnek söz konusu olmalıdır. İşlev başka parametrelere sahip olabilir ve adlandırılmış varlık bir veri üyesi veya belki de bir fonksiyonun kendisi olabilir.

C++ için düşündüğüm başka bir uzantı, makronun içeriğini alabilen bir sınıf NamedRef.

template <typename T> 
struct NamedRef 
{ 
    NamedRef(T *t, const char *name) : t(t), name(name) { } 
    T *t; 
    const char *name; 
}; 

template <typename T> 
NamedRef<T> namedRef(T &t, const char *name) 
{ 
    return NamedRef<T>(&t, name); 
} 

#define WITH_NAME(a) a, #a 

// more sophisticated usage example 
void otherFunction(double, NamedRef<int>, bool); 

otherFunction(0.0, namedRef(object.WITH_NAME(meaningful_member_name)), false); 
+3

Tek yapmam gereken makro için daha açıklayıcı bir ad seçmektir, örn. 'WITH_NAME() '. –

+0

@MarkRansom'un önerdiği şeyi yapın. Cevabım "iyi" demenin uzun bir yoluydu ve Boost'un "BOOST_STRINGIZE (X)" adlı bir makrosu var. – AusCBloke

cevap

5

Sen bir adım öteye götürebiliriz:

#define SOMEFUNCTION(a) somefunction(a, #a) 

Ancak, bu yalnızca yararlıdır aynı işlevi sürü dersen. Aksi halde, senin örneğinden daha iyi bir yol olduğunu düşünmüyorum. Tabii ki, makronun adını ARGUMENTS ya da bir şey gibi daha anlamlı bir şeye değiştirmelisiniz.

+0

Doğru, ancak "var, name" alan bir çok işlevim varsa, çok fazla makro yazmam gerekecek. – paperjam

+0

Mutlaka değil => '#define MACRO (funct_ptr, var) funct_ptr (var, #var)' Bu kadar çok makroya ihtiyacınız olan fonksiyon parametrelerinin ne kadar farklı imzasına sahip olmanız gerekir ... –

+0

Tamam, iyi düşünmek, ama Mümkünse işlev sözdizimini korumanın daha açık olduğunu düşünüyorum, ayrıca işlev başka hatalara da sahip olabilir. – paperjam

0
#define someFunction(a) if (1) stringized_someFunction((a), #a); else (void)0 
void stringized_someFunction(int a, const char* name); 

o

Ardından bu yüzden gibi işlev vb (genellikle) döngüler, dallar, eğer ifadeleri ile uğraşma, çağırır, böylece (1) malzeme makro tamamladı eğer:

int r = 4; 
someFunction(r); 

Her "işlev bildirimi" için gerçekten yalnızca bir satır ekliyorsunuz. Eğer C önişlemci birden fazla adım attıysa, hepsini birer birer içine alabilirdiniz, ama olmaz.

void stringized_someFunction(int a, const char* name) 
{ 
    // Do stuff here 
} 

neyse şekilde okumak için çok daha kolay ve daha güzel olmalı: Ben size işlevini iletişim kurmanız gerekir aşikardır umut çünkü

unuttum.

+1

Makro tanımınızdaki noktalı virgülü başka bir şeyden önce unuttun. Ayrıca, bu durumda (1) gerekli ise onu sarma düşünmüyorum. –

+0

@Jesse teşekkürler. eğer (1) eğer gerekli ise. –

+1

Kodları kesmelerini engellemek için [çok deyimli makroları sarmak zorundasınız] (http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Multi-statement_Macro), ama anlamıyorum. tek bir deyimin sebebi, eğer bir karşı örnek sağlayabilirseniz takdir edilecektir. –

0

Bu tür işler için XMACRO s kullanımının faydalı olduğunu düşünebilirsiniz.

0

Jesse cevap olarak,

böyle yazabilirsiniz:

void function1(int a, const char* name) 
{ 
    cout << "a: " << a << endl; 
    cout << "name: " << name << endl; 
} 

void function2(double d, const char* name, const char *str) 
{ 
    cout << "d: " << d << endl; 
    cout << "name: " << name << endl; 
    cout << "str: " << str << endl; 
} 

#define MACRO(functionName, a) functionName(a, #a) 
#define MACRO2(functionName, a, ...) functionName(a, #a, __VA_ARGS__) 

int main() 
{ 
    int a = 10; 
    MACRO(function1, a); 
    double d = 10.5; 
    MACRO2(function2, d, "Hello world"); 
    return 0; 
} 

daha argümanları varsa

geçmek, değişken argümanları kullanan macro2 kullanabilirsiniz. Fonksiyon ismini buna göre geçmek zorunda kalacaksınız.