Локали C++


Суть проблемы состоит в том, мне, к примеру, хотелось бы написать программу на C++,
одинаково работающую и в среде Linux, и в среде FreeBSD, и в Windows. Однако, как правило,
эти системы имеют совершенно разные системные кодировки - UTF-8, KOI8-R, CP1251.
В одном случае - символ занимает лишь один байт, а в другом - два байта. Простое
использование std::string эту проблему никак не затрагивает - и в результате появляются баги.
Между текущий стандарт C++ предлагает достаточно туманный и совсем не простой механизм фасетов
для переносимого преобразования локалей. К фасетам мы еще вернемся, а пока приведу пример
минимальной инициализации для корректной работы со строками в рамках, хотя бы, одной выбранной локали.

#include <iostream>
#include <string>

int main() {

// Setup C rtl locale
std::setlocale(LC_ALL, "");

// Setup  C++ rtl global default locale
std::locale::global(std::locale(""));

// Setup locales for streams
std::cout.imbue(std::locale());
std::cerr.imbue(std::locale());
std::clog.imbue(std::locale());

// Setup locales for wide streams
std::wcout.imbue(std::locale());
std::wcerr.imbue(std::locale());
std::wclog.imbue(std::locale());

// For correct io with wcin/wcout disconnect stream from wstream
std::ios::sync_with_stdio(false);

string a = "test";
wstring b = L"тест";
cout << a << " " << a.length() << endl;
wcout << b << " " << b.length() << endl;

return 0;

}

Если бы мы не установили локали, то скорее всего, длина первой
строки (а) была бы равна 4, а второй (b) - равна 8.