Я использую этот макрос препроцессора, чтобы «stringify» и легко возвращался из функции разрешения определений:
#define STRINGIFY_RETURN(x) case x: return #x ""
Это работает как очарование в среде MBSC с обычными строковыми литералами. Пример:
#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";
}
}
Однако мне приходилось все больше и больше переключаться на совместимость с Юникодом, и поэтому мне пришлось переписывать эту функцию, чтобы вернуть строки Юникода, которые требуют префикса с L
перед строковыми литералами. Итак, я попробовал:
#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";
}
}
Но это дает мне ошибки:
ошибка C2308: конкатенация несоответствующих строк
ошибка C2440: «возврат»: невозможно преобразовать из «const char [12]» в «const wchar_t *»
Я также попробовал:
#define STRINGIFY_RETURN_WIDE(x) case x: return L #x ""#define STRINGIFY_RETURN_WIDE(x) case x: return #x "" L
но не смотря ни на что, я не могу заставить его работать. Я ничего не понимаю об этом и не могу найти решение.
Я был бы очень признателен, если бы кто-то мог показать правильный способ сделать этот макрос так, чтобы он преобразовывался в строковый литерал Unicode.
Обновить:
#define STRINGIFY_RETURN_WIDE(x) case x: return L#x ""
не выдает ошибку C2440, но все равно дает мне C2308.
Обновление 2:
Я использую Microsoft Visual Studio 2013
У вас есть два основных варианта:
#define STRINGIFY_RETURN_WIDE(x) case x: return L#x L""
Это объединяет два L"…"
строки. Альтернативное и более простое решение — не объединять пустую строку:
#define STRINGIFY_RETURN_WIDE(x) case x: return L#x
Не ясно, есть ли польза от добавления пустой строки.
Как Роберт Прево отметил в комментарий, это не работает с G ++ и Clang ++,
хотя, кажется, работает на Vinzenz с его компилятором (Microsoft Visual Studio 2013).
Проблема в том, что препроцессор токенизирует свой ввод и широкий строковый литерал L"..."
все это один токен, но макрос выше пытается генерировать токены L
и «…», что приводит к проблемам:
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);
Существует обходной путь:
#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";
}
}
Проверено на Mac OS X 10.11.6 с GCC 6.2.0.
http://en.cppreference.com/w/cpp/preprocessor/replace
Показывает, что:
#define showlist(...) puts(#__VA_ARGS__)
showlist(); // expands to puts("")
showlist(1, "x", int); // expands to puts("1, \"x\", int")
Поскольку расширение включает в себя кавычки, я думаю, просто возвращение L # x будет желаемым результатом для широких символов.