2010-07-05 24 views
15

Tôi muốn xác định một macro trong đó bao gồm một tập tin tiêu đề như vậy:Sử dụng #define để bao gồm một tập tin trong C++/C

#define MY_MACRO (text) #include "__FILE__##_inline.inl" 

Vì vậy mà khi tiền xử lý phân tích tập tin person.h, MY_MACRO (blahblah) mở rộng đến

#include "person.h.inline.inl"

bất kỳ gợi ý nào về cách thực hiện việc này?

+2

Không thể thực hiện được. – Philipp

Trả lời

14

Không thể sử dụng #define để xây dựng các chỉ thị tiền xử lý khác, trừ khi bạn chạy bộ xử lý trước hai lần.

Nhưng trong trường hợp của bạn, ngay cả khi chạy bộ xử lý trước hai lần sẽ không giúp đỡ vì #include phải là một chuỗi duy nhất có dạng "..." hoặc <...>.

+1

Điều này là sai, tôi đã làm việc với mã đã làm điều này. Chúng bao gồm tệp nhiều lần, mỗi lần xác định lại macro trước khi bao gồm macro. Điều này làm cho các macro được chạy nhiều lần, một lần cho mỗi lần bao gồm. Trường hợp sử dụng tôi thấy là mã C thuần túy sử dụng thủ thuật này để tạo các mẫu giả. –

+0

@GabeSechan Những gì bạn mô tả thường được gọi là X Macro. Nhưng nó không chạy bộ tiền xử lý nhiều lần. Nó xác định lại các macro và bao gồm các tệp nhiều lần. Đó là một mẹo thực sự thú vị đối với một số trường hợp sử dụng. – woodtluk

3

Bạn không thể viết các chỉ thị tiền xử lý khác bằng bộ xử lý trước. Tuy nhiên, tôi tin rằng bạn có thể xác định chỉ là tên file:

#define MY_MACRO(name) "__FILE__##name_inline.inl" 

#include MY_MACRO(name) 

The pre-bộ xử lý chạy nhiều lần cho đến khi không có sự thay thế hơn nữa nó có thể làm, vì vậy nó nên mở rộng tên đầu tiên và sau đó #include file tham chiếu .

EDIT: Tôi vừa thử nó và bộ xử lý trước không thể xử lý các dấu ngoặc kép như thế.

#define MY_MACRO(x) <__FILE__##x_inline.inl> 
#include MY_MACRO(foo) 

hoạt động OK, nhưng <> có thể không phải là thứ bạn muốn.

EDIT2: Như được chỉ ra trong phần nhận xét, __FILE__ không mở rộng chính xác, điều này có thể không phải là điều bạn muốn sau khi tất cả. Lấy làm tiếc.

+1

http://codepad.org/AxNh2h3F Rõ ràng '" __FILE __ ## name_inline.inl "' được xử lý theo nghĩa đen, nhưng nếu bạn chuyển nó thành '#define MY_MACRO (tên) <__ FILE__ ## name ## _inline.inl>' thì bạn * có thể * thực sự bao gồm một tệp tin khác nhau. –

+0

Tôi không nghĩ rằng điều này làm việc cả. Macro bạn cung cấp mở rộng thành '<__ FILE__x_inline.inl>', trong khi macro này phải giống như ''. – sth

+0

@sth: Bạn hoàn toàn đúng, tôi đã bỏ lỡ điều đó. Tôi đã cố gắng phá vỡ nó xuống để hai giai đoạn cũng như: [code] #define MY_MACRO (a) __FILE__ ## một #define MY_MACRO_2 (b) #include MY_MACRO_2 (thử nghiệm) [/ code] nhưng điều đó cũng không giúp được gì. – Vicky

9

Bạn không thể sử dụng __FILE__ vì đã được trích dẫn và #include không hỗ trợ nối chuỗi. Nhưng bạn có thể sử dụng các macro sau #include:

#define STRINGIZE_AUX(a) #a 
#define STRINGIZE(a) STRINGIZE_AUX(a) 
#define CAT_AUX(a, b) a##b 
#define CAT(a, b) CAT_AUX(a, b) 
#define MY_MACRO(file, name) STRINGIZE(CAT(file, CAT(name, _inline.inl))) 
#include MY_MACRO(aaaa, qqq) 

Bạn nên sử dụng các macro Boost.Preprocessor tương đương thay vì CATSTRINGIZE để ngăn ngừa ô nhiễm không gian tên toàn cầu.

+0

+1 Tôi không chắc chắn nó rất xấu xí hay rất đẹp nhưng có vẻ như hoạt động ... – Tomas

+0

có nó không quản lý để bao gồm các tập tin, nhưng tôi vẫn phải sử dụng một #include riêng biệt, và cũng có vẻ như __FILE__ là được mở rộng thành một chuỗi được trích dẫn nên có thể điều này là không thể. –

+0

Vâng, nó thực sự là không thể. Hãy thử thiết kế lại ứng dụng của bạn để không cần thiết. – Philipp

-5
#if 0 /*Windows*/ 
#define MKDIR_ENABLER <direct.h> 
#define MY_MKDIR(x,y) _mkdir((x)) 
#else /*Linux*/ 
#define MKDIR_ENABLER <sys/stat.h> 
#define MY_MKDIR(x,y) mkdir((x),(y)) 
#endif 

#include MKDIR_ENABLER 

int main(void) 
{ 
    MY_MKDIR("more_bla",0644); 
    return 0; 
} 

Mã này bao gồm tệp tiêu đề thích hợp cho mkdir (vì nó khác trên UNIX và Windows) và giới thiệu trình bao bọc đẹp cho nó.

+0

Và theo cách này, câu trả lời là gì? – dhein

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