2009-12-18 43 views
5

Tôi có macro, trong đó một trong các đối số là giá trị enum, được đưa ra mà không chỉ định phạm vi không gian tên. Tuy nhiên một nơi nào đó bên trong vĩ mô tôi cần phải truy cập nó (rõ ràng tôi phải xác định không gian tên đó), nhưng tôi không thể có vẻ concat tên không gian tên với tham số mẫu. Cho samplecode sau trình biên dịch phàn nàn rằng pasting :: and Val doesnt give a valid preprocessor token (nó hoạt động tốt cho concating get và a để getVal).Đối số Macro đối số với không gian tên

namespace TN 
{ 
    enum Info 
    { 
     Val = 0 
    }; 
} 

#define TEST(a) TN::Info get ## a(){return TN::##a;} 
TEST(Val) 

Vậy có cách nào để làm cho công việc này mà không cần sử dụng lập luận khác và về cơ bản xác định giá trị được sử dụng hai lần (ví dụ #define TEST(a,b) TN::Info get ## a(){return b;})?

Trả lời

10

## là một nhà điều hành dán mã thông báo, nghĩa là phải tạo một mã thông báo trong nhiều bit mã thông báo và trình biên dịch cho biết, ::Val không phải là một mã thông báo duy nhất.

Tại sao bạn cần nghĩ rằng bạn cần số thứ hai ##? Có chuyện gì với cái này.

#define TEST(a) TN::Info get ## a() { return TN::a; } 
+0

rõ ràng là tôi đang suy nghĩ về cách phức tạp, cảm ơn – Grizzly

+0

@ Grizzly: Trớ trêu thay, ngược lại! Bản năng đầu tiên của tôi cũng là để nối, vì macro về cơ bản là tìm và thay thế văn bản thay thế. Đó là khi bạn nhận ra rằng họ _are_ phức tạp hơn điều này (trong đó họ làm việc trên _tokens_ và bộ não của chúng tôi không) rằng vấn đề như thế này đi lên. :) –

3

Chỉ sử dụng ## khi bạn muốn nối hai mục và yêu cầu trình biên dịch xử lý kết quả dưới dạng một mã thông báo duy nhất (ví dụ: số nhận dạng).

Trong macro của bạn, việc sử dụng ## đầu tiên là chính xác, vì bạn đang cố gắng tạo mã định danh bằng cách dán get và nội dung của a, nhưng việc sử dụng thứ hai ## là giả mạo, như bạn chỉ muốn thực hiện số nhận dạng ngoài nội dung của a và toán tử :: là một thực thể riêng biệt. GCC sẽ khiếu nại về điều này (mặc dù các đối tác của MSVC++).

#define TEST(a) TN::Info get ## a(){return TN::a;} 

sẽ hoạt động.

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