2010-10-03 720 views
5

GCC than phiền nếu tôi làm điều này:Tôi có thể định nghĩa các macro tiền xử lý variadic C với __VA_ARGS ở giữa thay vì kết thúc không?

#define M(obj,met, ..., contents) obj##_##met(const void * self, __VA_ARGS__) { \ 
    contents \ 
    } 

Cho tôi những 2 lý do:

error: missing ')' in macro parameter list 
warning: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro 

Rõ ràng, C99 - phong cách macro variadic mong đợi những đóng ngoặc ngay sau khi lược, hiệu quả đòi hỏi rằng variadic danh sách là đối số cuối cùng của macro. Tôi cần nó ở giữa để tạo ra ký pháp viết tắt của tôi được mô tả trong macro trên. GCC có hỗ trợ tính năng này hay không, sử dụng kiểu macro Variadic khác (không phải C99)? Tôi có thể mô phỏng nó làm việc này một cách khác không? Tôi không muốn danh sách variadic ở cuối, nó sẽ làm cho ký hiệu của tôi khó hiểu. Và tôi chỉ có thể sử dụng GCC.

+0

* Tôi không muốn danh sách variadic ở cuối, nó sẽ làm cho ký hiệu của tôi khó hiểu. Và tôi chỉ có thể sử dụng GCC. –

+0

Xem [Boost.Preprocessor] (http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/index.html). Tôi gần như chắc chắn bạn có thể làm điều đó miễn là bạn ngừng cố gắng xác định 'nội dung' như một đối số riêng biệt - bạn sử dụng một phần của công cụ tiền xử lý để xác định đối số cuối cùng của các đối số biến. Tất nhiên, định nghĩa phức tạp hơn một chút. –

Trả lời

7

Không, bạn không thể. ... phải xuất hiện ở cuối.

Nhưng bạn có thể xác định M như

#define M(obj,met, ...) obj##_##met(const void * self, __VA_ARGS__) 

và sử dụng nó như

void M(foo, bar, int x, char y, double z) { 
    content; 
} 
+0

: (đó là những gì tôi sợ. Cảm ơn bạn: D –

5

Bạn phải đặt ... ở cuối, nhưng sử dụng LASTPOP_LAST macro, bạn có thể giữ cùng thứ tự của các đối số cho macro của bạn và xác định nó như sau:

#define M(obj,met, ...) obj##_##met(const void * self, POP_LAST(__VA_ARGS__)) { \ 
    LAST(__VA_ARGS__) \ 
    } 

Heres làm thế nào bạn có thể định nghĩa các macro:

/* This counts the number of args */ 
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N 
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1) 

/* This will let macros expand before concating them */ 
#define PRIMITIVE_CAT(x, y) x ## y 
#define CAT(x, y) PRIMITIVE_CAT(x, y) 

/* This will pop the last argument off */ 
#define POP_LAST(...) CAT(POP_LAST_, NARGS(__VA_ARGS__))(__VA_ARGS__) 
#define POP_LAST_1(x1) 
#define POP_LAST_2(x1, x2) x1 
#define POP_LAST_3(x1, x2, x3) x1, x2 
#define POP_LAST_4(x1, x2, x3, x4) x1, x2, x3 
#define POP_LAST_5(x1, x2, x3, x4, x5) x1, x2, x3, x4 
#define POP_LAST_6(x1, x2, x3, x4, x5, x6) x1, x2, x3, x4, x5 
#define POP_LAST_7(x1, x2, x3, x4, x5, x6, x7) x1, x2, x3, x4, x5, x6 
#define POP_LAST_8(x1, x2, x3, x4, x5, x6, x7, x8) x1, x2, x3, x4, x5, x6, x7 

/* This will return the last argument */ 
#define LAST(...) CAT(LAST_, NARGS(__VA_ARGS__))(__VA_ARGS__) 
#define LAST_1(x1) x1 
#define LAST_2(x1, x2) x2 
#define LAST_3(x1, x2, x3) x3 
#define LAST_4(x1, x2, x3, x4) x4 
#define LAST_5(x1, x2, x3, x4, x5) x5 
#define LAST_6(x1, x2, x3, x4, x5, x6) x6 
#define LAST_7(x1, x2, x3, x4, x5, x6, x7) x7 
#define LAST_8(x1, x2, x3, x4, x5, x6, x7, x8) x8 

Những macro sẽ làm việc cho đến 8 đối số. Bạn có thể dễ dàng mở rộng chúng để xử lý nhiều hơn nếu bạn muốn.