2011-12-21 36 views
8

Tôi có nhiều biến được đặt tên giống như phần tử trong tài liệu kỹ thuật để phiên bản chuỗi của tên cũng hữu ích.Macro C/C++ mở rộng thành đối số, đối số dưới dạng chuỗi

tôi thấy mình sử dụng một macro như thế này rất nhiều:

#define MACRO(a) a, #a 

sử dụng điển hình là:

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

someFunction(MACRO(meaningfully_named_variable)); 

Câu hỏi của tôi có ba điểm:

  • Có một cách tốt hơn làm điều này?
  • Macro tương tự có sẵn trong Boost hoặc các thư viện khác không?
  • Nếu không, làm thế nào tôi có thể tinh chỉnh và đổi tên nó để làm cho nó rõ ràng và hữu ích?

Sửa tôi nên đã nói rằng ở trên là một ví dụ rất nhỏ. Hàm này có thể có các tham số khác và thực thể được đặt tên có thể là một thành viên dữ liệu hoặc thậm chí có thể là một hàm.

Một tiện ích mở rộng khác mà tôi đang xem xét cho C++ là một lớp NamedRef có thể nhận được nội dung của macro.

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

Tất cả những gì tôi muốn làm là chọn một tên mô tả hơn cho macro, ví dụ: 'WITH_NAME()'. –

+0

Làm những gì @MarkRansom đề xuất. Câu trả lời của tôi là một cách dài để nói "nó tốt" và Boost có một macro gọi là 'BOOST_STRINGIZE (X)'. – AusCBloke

Trả lời

5

Bạn có thể mang nó một bước xa hơn:

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

Tuy nhiên, đây chỉ là hữu ích nếu bạn gọi chức năng tương tự rất nhiều. Nếu không, tôi không nghĩ có cách nào tốt hơn ví dụ của bạn. Tất nhiên, bạn nên thay đổi tên của macro thành một cái gì đó có ý nghĩa hơn mặc dù, như ARGUMENTS hoặc một cái gì đó.

+0

Đúng, nhưng nếu tôi có rất nhiều hàm nhận 'var, name' thì tôi sẽ phải viết rất nhiều macro. – paperjam

+0

Không nhất thiết => '#define MACRO (funct_ptr, var) funct_ptr (var, #var)' Vì vậy, bạn sẽ cần nhiều macro như vậy có bao nhiêu chữ ký khác nhau của các tham số hàm bạn có ... –

+0

OK, suy nghĩ tốt, nhưng Tôi nghĩ rằng nó rõ ràng hơn để bảo toàn cú pháp hàm nếu có thể, cũng có chức năng có thể có các arg khác. – paperjam

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

Các if (1) thứ kết thúc tốt đẹp vĩ mô để nó sẽ không gây rối (thường) với các vòng, chi nhánh, nếu báo cáo vv

Bạn sẽ sau đó gọi chức năng của bạn như sau:

int r = 4; 
someFunction(r); 

Bạn chỉ thực sự thêm một dòng phụ cho mỗi "khai báo hàm". Nếu bộ tiền xử lý C cho phép nhiều bước bạn có thể gói tất cả thành một, nhưng than ôi, nó không.

Tôi quên bởi vì tôi hy vọng nó là rõ ràng rằng bạn cần phải viết hàm của bạn:

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

Nhưng dù sao nó phải được dễ dàng hơn rất nhiều và đẹp hơn để đọc theo cách đó.

+1

Bạn đã quên dấu chấm phẩy trong định nghĩa macro của mình trước khi khác. Ngoài ra, tôi không nghĩ rằng gói nó trong nếu (1) là cần thiết trong tình huống này. –

+0

@Xin cảm ơn. gói trong nếu (1) luôn luôn là cần thiết. –

+1

Tôi biết rằng bạn [cần phải bọc các macro đa tuyên bố] (http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Multi-statement_Macro) để ngăn chúng phá vỡ mã, nhưng tôi không hiểu lý do cho các câu lệnh đơn, nếu bạn có thể cung cấp một ví dụ ngược, nó sẽ được đánh giá cao. –

0

Bạn có thể thấy rằng XMACRO s rất hữu ích cho loại công việc này.

0

Như Jesse trả lời,

bạn có thể viết như thế này:

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; 
} 

Nếu bạn có nhiều lý lẽ để vượt qua, bạn có thể sử dụng MACRO2 sử dụng đối số biến. Bạn sẽ phải chuyển tên hàm cho phù hợp.

Các vấn đề liên quan