Я знаю, что уже существует несколько вопросов на StackOverflow о std::string
по сравнению с std::wstring
или подобный, но ни один из них не предложил полного решения.
Для получения хорошего ответа, я должен определить требования:
CFStringRef
, wchar_t *
, char*
как UTF-8 или другие типы, поскольку они требуются ОС API. Комментарий: Мне не нужна кодовая страница convertion поддержка, потому что я ожидаю использовать только Unicode совместимые функции во всех поддерживаемых операционных системах.Я был бы очень признателен за только одно предлагаемое решение на ответ путем выполнения этого, люди могут голосовать за свою предпочтенную альтернативу. Если у Вас есть больше чем одна альтернатива, просто добавляют другой ответ.
Укажите на что-то, что сделало работавший для Вас.
Связанные вопросы:
Мне кажется, что у вас на самом деле есть два разных поведения в одном классе.
Примечательно, кажется, что вы можете пройти только вашу коллекцию в одном порядке, в противном случае, если вы должны были начать обход, а затем изменить аргумент
, вы получите довольно странную ситуацию.
Лично я все для разоблачения обоих итераторов (т. Е. Вперед начинается, конец, rbegin и Rind
).
Вы также можете вернуть простой объект ITERATOR:
template <class T>
class Iterator
{
public:
typedef typename T::reference_type reference_type;
Iterator(T it, T end) : m_it(it), m_end(end) {}
operator bool() const { return m_it != m_end; }
reference_type operator*() const { return *m_it; }
Iterator& operator++() { ++m_it; return *this; }
private:
T m_it;
T m_end;
};
template <class T>
Iterator<T> make_iterator(T it, T end) { return Iterator<T>(it,end); }
затем вы можете просто вернуть этот простой объект:
class Action
{
public:
Action(std::deque<Move> const& d): m_deque(d) {} // const& please
typedef Iterator< std::deque<Move>::iterator > forward_iterator_type;
typedef Iterator< std::deque<Move>::reverse_iterator > backward_iterator_type;
forward_iterator_type forward_iterator()
{
return make_iterator(m_deque.begin(), m_deque.end());
}
backward_iterator_type backward_iterator()
{
return make_iterator(m_deque.rbegin(), m_deque.rend());
}
private:
std::deque<Move> m_deque;
};
или если вы хотите динамически выбрать между передней и обратной траверсом, вы можете сделать итератор чистый виртуальный интерфейс и Имея вперед, так и назад.
Но на самом деле я на самом деле не вижу смысла хранить вперед и назад и обратный итератор, если окажется, что вы будете использовать только один: /
-121--1141568-То же, что и ADAM Rosenfield Action (+1), но я использую UTFCPP вместо этого.
Я был недавно в проекте, который решил использовать STD :: WSTRing для кроссплатформенного проекта, потому что «Широкие строки - это Unicode, верно?» Это привело к ряду головных болей:
Когда вы находитесь в конкретном платформе кода, имеет смысл использовать собственное представление платформы для общения с его API. Но для любого кода, который передается через платформы, или связывается между платформами, избегайте всю двусмысленность и использовать UTF-8.
Я бы пошел на представление UTF16 в памяти и UTF-8 или 16 на жестком диске или проводе. Основная причина: UTF16 имеет фиксированный размер для каждой «буквы». Это упрощает много обязанностей при работе со строкой (поиск, замена деталей, ...).
Единственная причина для UTF-8 - снижение использования памяти для букв «Western / Latin». Вы можете использовать это представление для дискового хранения или транспортировки по сети. Он также имеет преимущество, которое вам не нужно беспокоиться о том, как загрузка / сохранение на диск / провод.
По мнению этих причин, я бы пошел на STD :: Wstring внутри или - если ваша библиотека GUI предлагает широкоподъемное, используйте это (например, QString от Qt). И для хранения дисков я бы написал небольшую платформу независимую обертку для платформы API. Или я бы проверил Unicode.org, если у них есть платформерный код, доступный для этого преобразования.
Для пояснения: корейские / японские буквы не являются западными / латыними. Японцы для экзамена Kanji. Вот почему я упомянул набор латинского персонажа.
Для UTF-16 не является 1 символом / 2 байта. Это предположение верно только для персонажей, находящихся на базовой многоязычной плоскости (см.: http://en.wikipedia.org/wiki/utf16 ). Еще большинство пользователей UTF-16 предполагают, что все символы на BMP. Если это не может быть гарантировано для вашего приложения, вы можете переключиться на UTF32 или переключиться на UTF8.
Все еще UTF-16 используется по причинам, упомянутым выше во многих API (например, WXW, QT, Java, .NET, WXWidgets)
Я настоятельно рекомендую использовать UTF-8 внутри вашего приложения, используя регулярные старые Char *
или STD :: string
для хранения данных. Для взаимодействия с API, которые используют другое кодирование (ASCII, UTF-16 и т. Д.), Я бы порекомендовал использовать libiconv , который лицензирован под LGPL.
Пример использования:
class TempWstring
{
public:
TempWstring(const char *str)
{
assert(sUTF8toUTF16 != (iconv_t)-1);
size_t inBytesLeft = strlen(str);
size_t outBytesLeft = 2 * (inBytesLeft + 1); // worst case
mStr = new char[outBytesLeft];
char *outBuf = mStr;
int result = iconv(sUTF8toUTF16, &str, &inBytesLeft, &outBuf, &outBytesLeft);
assert(result == 0 && inBytesLeft == 0);
}
~TempWstring()
{
delete [] mStr;
}
const wchar_t *Str() const { return (wchar_t *)mStr; }
static void Init()
{
sUTF8toUTF16 = iconv_open("UTF-16LE", "UTF-8");
assert(sUTF8toUTF16 != (iconv_t)-1);
}
static void Shutdown()
{
int err = iconv_close(sUTF8toUTF16);
assert(err == 0);
}
private:
char *mStr;
static iconv_t sUTF8toUTF16;
};
iconv_t TempWstring::sUTF8toUTF16 = (iconv_t)-1;
// At program startup:
TempWstring::Init();
// At program termination:
TempWstring::Shutdown();
// Now, to convert a UTF-8 string to a UTF-16 string, just do this:
TempWstring x("Entr\xc3\xa9""e"); // "Entrée"
const wchar_t *ws = x.Str(); // valid until x goes out of scope
// A less contrived example:
HWND hwnd = CreateWindowW(L"class name",
TempWstring("UTF-8 window title").Str(),
dwStyle, x, y, width, height, parent, menu, hInstance, lpParam);
Недостатком метода является то, что потребляющий код должен знать, какие ключи использовать для места хранения и извлечения. Это может быть причиной ошибки, так как ключ должен быть точно правильным, или вы рискуете сохранить в неправильном месте, или получить нулевое значение назад.
Я на самом деле использую сильно типизированный вариант, так как я знаю, что мне нужно иметь в сеансе, и, таким образом, могу настроить класс обертывания на соответствие. У меня скорее есть дополнительный код в сеансовом классе, и не нужно беспокоиться о ключевых последовательностях где-либо еще.
-121--4321269-Рекомендуется инициализировать память/переменные до их использования - неинициализированные переменные являются большим источником ошибок, которые часто очень трудно отследить.
Инициализация всех данных является очень хорошей идеей при записи их в формат файла: Он обеспечивает чистоту содержимого файла, так что они легче работать с, менее склонны к проблемам, если кто-то неправильно пытается «использовать» неинициализированные данные (помните, что это может быть не только ваш собственный код, который считывает данные в будущем), и делает файлы гораздо более сжимаемыми.
Единственная веская причина не инициализировать переменные до их использования - это критические для производительности ситуации, когда инициализация технически «не нужна» и влечет за собой значительные издержки. Но в большинстве случаев инициализация переменных не причинит существенного вреда (особенно если они объявлены непосредственно перед их использованием), но сэкономит вам много времени на разработку, устранив общий источник ошибок.
-121--3223106-Правило: используйте для обработки форму Юникод собственной платформы (UTF-16 или UTF-32), а для обмена данными (связь, место хранения) - UTF-8.
Если все собственные API используют UTF-16 (например, в Windows), имея свои последовательности в качестве UTF-8 означает, что вам придется конвертировать все входные данные в UTF-16, вызвать Win API, а затем преобразовать ответ в UTF-8. Довольно боль.
Но если основной проблемой является пользовательский интерфейс, то последовательности являются простой проблемой. Более сложной является структура пользовательского интерфейса. И для этого я бы рекомендовал wxWidgets ( http://www.wxWidgets.org ). Поддерживает множество платформ, зрелые (17 лет и все еще очень активные), родные виджеты, Unicode, либеральную лицензию.