2009-08-11 40 views
7

Ban đầu tôi nghĩ tôi cần điều này, nhưng cuối cùng tôi đã tránh nó. Tuy nhiên, sự tò mò của tôi (và thèm ăn cho kiến ​​thức, hum) làm cho tôi hỏi:Mở rộng macro tiền xử lý cho một chỉ thị tiền xử lý khác

thể macro tiền xử lý, ví dụ trong

#include "MyClass.h" 

INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass) 

mở rộng khác bao gồm, như trong

#include "MyClass.h" 

#include "FooTemplate.h" 
template class FooTemplate<MyClass>; 

?

+2

Một ngày bạn sẽ muốn chuyển mã của mình sang một hệ điều hành như Linux, trong đó trường hợp có ý nghĩa (nghĩa là Foo.h và foo.h là hai tệp khác nhau) và sau đó tất cả các lỗi chính tả không bị bắt gặp trên Windows sẽ trở về nhà roost. cách khác, nếu bạn là một người Linux, bạn sẽ một ngày nào đó muốn đi theo một cách khác, với những vấn đề khác nhau nhưng không kém phần kinh khủng. –

+1

Tôi đồng ý với quy tắc luôn có chữ thường cho tên tệp. Tôi đã viết theo cách này bởi vì tôi muốn loại trừ vấn đề chuyển đổi chữ thường (tên lớp -> tên tệp). Nhưng đó là giá trị đề cập đến, cảm ơn. +1! – moala

+0

Quy tắc của chúng tôi là tên tệp khớp chính xác với lược đồ đặt tên cho các loại và chức năng của chúng tôi. Chúng tôi làm chính xác như người hỏi ở đây, một loại tên FooType sẽ được định nghĩa trong FooType.h. Như với bất kỳ hướng dẫn "phong cách", chọn một phong cách và gắn bó với nó. Có nói rằng chúng tôi phát triển mạnh mẽ trên Linux và vì vậy quy tắc này được tự động thực thi cho chúng tôi bởi hệ điều hành .... hmmmmm ..... –

Trả lời

12

Tôi tin rằng không thể thực hiện được, điều này là do bộ xử lý trước là một lần. Vì vậy, nó không thể phát ra các chỉ thị tiền xử lý khác.

Cụ thể, từ tiêu chuẩn C99 (6.10.3.4 đoạn 3):

3 Các kết quả hoàn toàn vĩ mô thay thế tiền xử lý thẻ chuỗi không được xử lý như một chỉ thị tiền xử lý ngay cả khi nó giống một , ...

Điều thú vị đủ, Đây là lý do tại sao toán tử đơn nhất _Pragma được thêm vào c99. Vì không thể phát hiện được #pragma bởi các macro nhưng có thể là _Pragma.

+0

Vâng, tất nhiên nó có thể phát ra các chỉ thị. những gì nó không thể làm là xử lý chúng trong cùng một tiền xử lý. –

+1

Vì các ký tự '#' và '##' có ý nghĩa đặc biệt trong các macro, tôi không thấy làm thế nào bạn có thể phát ra một chỉ thị ... –

+0

Thực ra, bộ tiền xử lý GCC dường như cho phép "#define X #ifdef X" không gian giữa #ifdef và X thứ hai thực sự là một dòng mới, và điều này thực sự phát ra một #ifdef khi bạn chạy cpp trên nó. Một người khác có thể muốn kiểm tra điều này, vì tôi vừa có một vài loại bia :-) –

9

Tiêu chuẩn C nói này về tiền xử lý chỉ thị (C99 - 6.10 (2) - chỉ thị tiền xử lý):

Một chỉ thị tiền xử lý bao gồm một chuỗi các thẻ tiền xử lý bắt đầu với một thẻ # tiền xử lý đó (lúc bắt đầu giai đoạn dịch 4) ...

và (C99 - 6.10 (7)):

Các mã thông báo tiền xử lý trong một chỉ thị tiền xử lý không bị macro mở rộng trừ khi có quy định khác.

VÍ DỤ Trong:

#define EMPTY 
EMPTY # include <file.h> 

chuỗi các thẻ tiền xử lý trên dòng thứ hai không phải là một chỉ thị tiền xử lý, bởi vì nó không bắt đầu bằng một dấu # ở đầu giai đoạn dịch 4, mặc dù nó sẽ làm vì vậy sau khi EMPTY macro đã được thay thế

Vì vậy, không, macro không thể mở rộng thành chỉ thị tiền xử lý '#include'. Những chỉ thị này cần phải được thực hiện khi bắt đầu giai đoạn dịch 4 (khi xử lý các chỉ thị đó diễn ra tiền xử lý xảy ra). Kể từ khi mở rộng vĩ mô xảy ra trong giai đoạn 4, macro không thể gây ra một cái gì đó để tồn tại lúc bắt đầu giai đoạn 4.

Tôi muốn chỉ ra tuy nhiên, rằng sau không công việc:

#ifdef WIN32 
#define PLATFORM_HEADER "platform/windows/platform.h" 
#else 
#define PLATFORM_HEADER "platform/linux/platform.h" 

#include PLATFORM_HEADER 

vì tiêu chuẩn C cho biết điều này (C99, 6.10.2 (4) - Nguồn tập tin bao gồm):

Một chỉ thị tiền xử lý của mẫu

# include pp-tokens new-line 

(mà không phù hợp với một trong hai hình thức trước đó) được phép. Tiền xử lý mã thông báo sau khi đưa vào trong chỉ thị được xử lý giống như trong văn bản thông thường. (Mỗi định danh hiện định nghĩa là một tên vĩ mô được thay thế bằng danh sách thay thế của tokens tiền xử lý.)

+0

tôi đã xem phần đó của tiêu chuẩn, nhưng tôi không nghĩ đó là phần phù hợp nhất. Ví dụ không phải là một ví dụ cố gắng phát ra một chỉ thị. Thay vào đó, nó là một ví dụ về một chỉ thị không được đặt trước bởi "khoảng trắng" (mặc dù macro EMPTY giải quyết thành khoảng trắng). –

+1

Tôi đồng ý rằng trích dẫn của bạn từ tiêu chuẩn có liên quan trực tiếp hơn, nhưng nó không có ở đó khi tôi trả lời.Ngay cả khi ví dụ trên không giống như những gì được hỏi, thì bit về chỉ thị tiền xử lý cần phải được đặt ở đầu giai đoạn 4 cũng không cho phép macro mở rộng thành các chỉ thị tiền xử lý hữu ích, ngay cả khi 6.10.3.4 (3) nói trực tiếp hơn. (nói cách khác, ngay cả khi tôi không nghĩ rằng câu trả lời của tôi là không chính xác, thì rõ ràng bạn là một câu trả lời tốt hơn). –

+0

Đủ công bằng, bạn tạo một điểm tốt, +1 :-). –

1

Tất cả các chỉ thị tiền xử lý được giải thích trước khi mở rộng vĩ mô bắt đầu, vì vậy không, bạn có thể không có một vĩ mô mở rộng sang một # bao gồm chỉ thị và được giải thích như vậy. Thay vào đó, nó sẽ được hiểu là mã C++ (sai).

+0

Bạn có thể nhận được hiển thị này vì nhiều chỉ thị vô hiệu hóa việc mở rộng macro đối số của chúng, nhưng điều này không đúng. Macro mở rộng xảy ra đồng thời với phân tích cú pháp chỉ thị. Nếu đúng, #if sẽ không hoạt động và #undef sẽ không có tác dụng mà mọi người mong đợi. – zwol

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