使用Unicode字符串文字对String进行字符串化

时间:2016-09-09 02:54:29

标签: c++ c macros c-preprocessor stringification

我正在使用这个预处理器宏来进行"字符串化"并从定义解析函数中轻松返回:

#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兼容性,所以我不得不重写这个函数来返回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";
    }
}

但这给了我错误:

  

错误C2308:连接不匹配的字符串

     

错误C2440:'返回' :无法转换为' 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

2 个答案:

答案 0 :(得分:6)

您有两个主要选择:

#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中注明comment,这不适用于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";
    }
}

使用GCC 6.2.0在Mac OS X 10.11.6上检查。

答案 1 :(得分:2)

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将是宽字符所需的结果。