2016-09-09 13 views
7

Tôi đang sử dụng tiền xử lý macro này để "stringify" và trở lại một cách dễ dàng từ một chức năng giải quyết các định nghĩa:stringify Macro với Unicode Chuỗi Literal

#define STRINGIFY_RETURN(x) case x:  return #x "" 

Nó hoạt động như một nét duyên dáng trong môi trường MBSC với xâu bình thường. Ví dụ:

#define MY_DEFINE_1 1 
#define MY_DEFINE_2 2 
#define MY_DEFINE_3 3 

const char* GetMyDefineNameA(unsigned int value) 
{ 
    switch(value) 
    { 
     STRINGIFY_RETURN(MY_DEFINE_1); 
     STRINGIFY_RETURN(MY_DEFINE_2); 
     STRINGIFY_RETURN(MY_DEFINE_3); 
     default: return "Unknown"; 
    } 
} 

Tuy nhiên tôi đã phải chuyển sang Unicode tương thích ngày càng nhiều và vì vậy tôi đã phải viết lại chức năng này để trả lại chuỗi Unicode đòi hỏi các prefixing với L ở phía trước của xâu. Vì vậy, tôi đã cố gắng:

#define STRINGIFY_RETURN_WIDE(x) case x:  return #x L"" 

const wchar_t* GetMyDefineNameW(unsigned int value) 
{ 
    switch(value) 
    { 
     STRINGIFY_RETURN_WIDE(MY_DEFINE_1); 
     STRINGIFY_RETURN_WIDE(MY_DEFINE_2); 
     STRINGIFY_RETURN_WIDE(MY_DEFINE_3); 
     default: return L"Unknown"; 
    } 
} 

Nhưng điều đó mang lại cho tôi những lỗi:

lỗi C2308: concatenating dây không phù hợp

lỗi C2440: 'return': không thể chuyển đổi từ 'const char [12] 'thành' wchar_t * const

tôi cũng đã cố gắng:

#define STRINGIFY_RETURN_WIDE(x) case x:  return L #x "" 
#define STRINGIFY_RETURN_WIDE(x) case x:  return #x "" L 

nhưng không có vấn đề gì, tôi không thể làm cho nó hoạt động. Tôi không biết gì về điều này và dường như không tìm được giải pháp.

Tôi thực sự biết ơn nếu ai đó có thể hiển thị đúng cách để thực hiện macro này để giải quyết thành chuỗi Unicode.

Cập nhật:

#define STRINGIFY_RETURN_WIDE(x) case x:  return L#x "" 

không ném lỗi C2440, nhưng nó vẫn mang lại cho tôi những C2308.

Cập nhật 2:

Tôi đang sử dụng Microsoft Visual Studio 2013

+1

Bạn nên in ra tệp đã được xử lý trước để xem chính xác trình biên dịch được tạo ra, và sau đó làm việc từ đó. – PaulMcKenzie

+0

Bạn không chỉ muốn: #define STRINGIFY_RETURN_WIDE (x) case x: return L # x "" –

+0

@TimBeaudet Tôi vừa thử, nó mang lại cho tôi C2308 nhưng lỗi C2440 đã biến mất:/ – Vinzenz

Trả lời

5

Bạn có hai lựa chọn chính:

#define STRINGIFY_RETURN_WIDE(x) case x: return L#x L"" 

này nối hai L"…" chuỗi. Giải pháp thay thế và đơn giản hơn là không ghép chuỗi rỗng:

#define STRINGIFY_RETURN_WIDE(x) case x: return L#x 

Không rõ là có lợi ích gì khi nối thêm một chuỗi rỗng.


Như Robert Prévost lưu ý trong một comment, điều này không làm việc với G ++ và Clang ++, mặc dù nó có vẻ làm việc cho Vinzenz với trình biên dịch của mình (Microsoft Visual Studio 2013).

Vấn đề là Preprocessor tokenizes đầu vào của nó, và một chuỗi rộng đen L"..." là tất cả một chiếc thẻ, nhưng macro trên cố gắng để tạo ra thẻ L và "..." `, dẫn đến các vấn đề:

xx11.cpp:5:49: error: ‘L’ was not declared in this scope 
#define STRINGIFY_RETURN_WIDE(x) case x: return L#x 
               ^
xx11.cpp:11:9: note: in expansion of macro ‘STRINGIFY_RETURN_WIDE’ 
     STRINGIFY_RETURN_WIDE(MY_DEFINE_1); 

có một workaround:

#define MY_DEFINE_1 1 
#define MY_DEFINE_2 2 
#define MY_DEFINE_3 3 

#define LSTR(x) L ## x 
#define STRINGIFY_RETURN_WIDE(x) case x: return LSTR(#x) 

const wchar_t* GetMyDefineNameW(unsigned int value) 
{ 
    switch(value) 
    { 
     STRINGIFY_RETURN_WIDE(MY_DEFINE_1); 
     STRINGIFY_RETURN_WIDE(MY_DEFINE_2); 
     STRINGIFY_RETURN_WIDE(MY_DEFINE_3); 
     default: return L"Unknown"; 
    } 
} 

Kiểm tra trên Mac OS X 10.11.6 với GCC 6.2.0.

+0

Cảm ơn một lần nữa, điều đó đã hiệu quả. Tôi có thể hỏi mặc dù có bất kỳ lý do nào có thể tại sao một người sẽ nối một chuỗi rỗng trong macro đó? Tôi đã nhìn thấy nó nhiều lần trong khi tìm kiếm điều này. Để lại những bản thảo trống ra và tôi hạnh phúc, đó chỉ là sự tò mò của tôi. – Vinzenz

+1

Điều này không hiệu quả với clang ++. Chỉ để hoàn thành, xác định hai macro. #define _T (x) L ## x # define STRINGIFY_RETURN_WIDE (x) case x: return _T (#x). –

+0

@ RobertPrévost: Thật thú vị; vấn đề có liên quan đến tokenization và làm thế nào L là, hoặc không, được coi là một phần của chuỗi. Tôi nghi ngờ rằng 'clang ++' đang dùng một vie đúng hơn về mọi thứ, nhưng nó có nghĩa là nếu bạn cần sử dụng toán tử '#' và một tiền tố kiểu chuỗi, thì bạn bị mắc kẹt với kỹ thuật dual-macro đề cương. Cảm ơn bạn đã chỉ ra điều đó. –

2

http://en.cppreference.com/w/cpp/preprocessor/replace

Cho thấy:

#define showlist(...) puts(#__VA_ARGS__) 
showlist();   // expands to puts("") 
showlist(1, "x", int); // expands to puts("1, \"x\", int") 

Kể từ khi mở rộng bao gồm các dấu ngoặc kép, tôi nghĩ đơn giản là trở L #x sẽ là kết quả mong muốn của bạn cho các ký tự rộng.