Создание строковых и широких строковых литералов из одного определения - PullRequest
0 голосов
/ 12 мая 2019

Иногда необходимо создать строковые литералы с одинаковым значением для типов 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, чтобы заставить его работать?

Ответы [ 2 ]

2 голосов
/ 12 мая 2019

Вам просто нужен другой макрос, поэтому аргумент макроса раскрывается перед вставкой:

#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);
0 голосов
/ 12 мая 2019

Вряд ли вам нужны обе версии в правильном дизайне.В любом случае, эти два типа (char и wchar_t) несовместимы (8/16 бит), поэтому вы не можете сделать это на уровне компиляции.

Разработайте класс, который использует wchar_t и преобразует всимвол только при необходимости.Для этого вы используете WideCharToMultiByte .

При проектировании всего приложения используйте только широкие символы и используйте только формы UTF-8 при сериализации.

...