从单个定义创建字符串和宽字符串文字

时间:2019-05-12 20:19:49

标签: c++ c string windows macros

有时需要为char *wchar_t *类型创建具有相同值的字符串文字(例如,在Windows中开发时)。一种简单的方法是两次定义:

const char *my_string = "Hello World";
const wchar_t *my_wide_string = L"Hello World";

问题是,如果我们需要更改字符串而不是仅更改一个位置,则两行都需要更新,这通常会导致错别字和错误。理想情况下,文字应该只出现一次,并且从中填充两个变量。

我们可以定义char变量,并在运行时将其转换为wchar_t版本。但是,最好避免运行时开销,因为文字在编译时就已经可用。

我曾考虑使用令牌粘贴运算符,但由于仅接受另一个字符串文字而无法使其工作:

#define my_string "Hello World"
#define make_wide(str) L##str
#define my_wide_string make_wide(my_string)  // expand to Lmy_string instead of L"Hello World"

我不确定是否可以使用constexpr使其正常工作?

3 个答案:

答案 0 :(得分:2)

您只需要另一个宏,以便在粘贴之前扩展该宏的参数:

#include <wchar.h>

#define my_string "Hello World"

#define WidenHelper(x)  L##x
#define Widen(x)        WidenHelper(x)

const char *plain   = my_string;
const wchar_t *wide = Widen(my_string);

答案 1 :(得分:0)

您不太可能希望两个版本都采用适当的设计。无论如何,这两种类型(charwchar_t)不兼容(8/16位),因此您不能在编译级别执行此操作。

设计一个使用wchar_t的类,并仅在必要时将其转换为char。为此,您使用WideCharToMultiByte

将整个应用程序设计为仅使用宽字符,并在序列化时仅使用UTF-8形式。

答案 2 :(得分:0)

由于您使用的是Windows,因此可以在_STR2WSTR中包含的crtdefs.h中使用#include <windows.h>。他们还以普通的字符串变体形式制作了__FILEW____FUNCTIONW__

/* error reporting helpers */
#define __STR2WSTR(str)    L##str
#define _STR2WSTR(str)     __STR2WSTR(str)

#define __FILEW__          _STR2WSTR(__FILE__)
#define __FUNCTIONW__      _STR2WSTR(__FUNCTION__)