使用 Unicode 字符串文字 Stringify 宏

Stringify Macro with Unicode String Literal

我正在使用这个预处理器宏从定义解析函数轻松地 "stringify" 和 return:

#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";
    }
}

但是我不得不越来越多地切换到 Unicode 兼容性,所以我不得不将此函数重写为 return Unicode 字符串,它需要在字符串文字前面加上 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";
    }
}

但这给了我错误:

error C2308: concatenating mismatched strings

error C2440: 'return' : cannot convert from 'const char [12]' to '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

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")

由于扩展包含引号,我认为 return L#x 将是您想要的宽字符结果。

您有两个主要选择:

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

这将连接两个 L"…" 字符串。另一种更简单的解决方案是不连接空字符串:

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

尚不清楚附加空字符串是否有任何好处。


Robert Prévost noted in a 一样,这不适用于 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 上检查。