// ...

Конструктор только инициализирует два члена, которые могут быть любого типа, но нам нужно, чтобы это был указатель на функцию и некоторый параметр p любого типа. Ради повышения эффективности я сохраняю адрес параметра, а не его значение.

Теперь рассмотрим следующую строку главного потока.

boost::thread thr1(Adapter<WorkerFunPtr, std::string>(worker, s1))

Аргумент конструктора thr1 представляет собой реализацию шаблона класса Adapter, использующую в качестве параметров два типа WorkerFunPtr и std::string. Это именно те два типа, которые являются членами адаптера f_ и p_. Наконец, Adapter перегружает operator(), поэтому он может вызываться как функция. Его вызов означает просто выполнение следующей функции.

f_(*p_);

Применяя шаблон класса Adapter, можно передавать аргументы функциям потока, причем делается это за счет лишь небольшого усложнения синтаксиса. Если требуется передавать еще один аргумент, просто добавьте дополнительный тип и переменную-член в шаблон Adapter. Этот подход привлекателен тем, что позволяет создавать набор шаблонов классов обобщенного адаптера и использовать их в различных контекстах.

Глава 13

Интернационализация

13.0. Введение

В данной главе приводятся решения некоторых задач, которые обычно возникают при интернационализации программ С++. Обеспечение возможности работы программы в различных регионах (это обычно называется локализацией), как правило, требует решения двух задач: форматирования строк, воспринимаемых пользователем, в соответствии с местными соглашениями (например, даты, времени, денежных сумм и чисел) и обеспечения работы с различными символьными наборами. В настоящей главе рассматривается в основном первая проблема и только кратко вторая, потому что имеется немного возможностей по стандартизации поддержки различных символьных наборов из-за того, что такая поддержка во многом зависит от реализации.

Большая часть программного обеспечения будет работать в странах, отличных от той, где они были написаны. Для поддержки этой практики стандартная библиотека C++ имеет несколько средств, способствующих написанию программного кода, предназначенного для работы в различных странах. Однако они спроектированы не так. как многие другие средства стандартной библиотеки, например строки, файловый ввод-вывод, контейнеры, алгоритмы и т.п. Например, класс, представляющий локализацию, имеет имя locale и содержится в заголовочном файле <lосаlе>. Класс locale предоставляет средства для записи и чтения потоков с применением специфичного для данной местности форматирования и получения таких сведений о локализации, как, например, ее символ валюты или формат даты. Однако стандартом предусматривается обеспечение только одной локализации, и этой локализацией является «C»-локализация, или классическая локализация. Классическая локализация использует стандарт ANSI С: принятые в американском варианте английского языка соглашения по форматированию и 7-битовой код ASCII. И от реализации зависит, будут ли обеспечены экземпляры locale для других языков и регионов.

Заголовочный файл <locale> имеет три основные части. Во-первых, это класс locale (локализация). Он инкапсулирует все поддерживаемые в C++ особенности локализованного поведения и обеспечивает точки входа для получения различной информации о локализации, необходимой для выполнения локализованного форматирования. Во-вторых, самыми маленькими элементами локализации и конкретными классами, с которыми вы будете работать, являются классы, называемые фасетами (facets). Примером фасета является, например, класс time_put, предназначенный для записи даты в поток. В-третьих, каждый фасет принадлежит к некоторой категории, которая объединяет связанные фасеты в одну группу. Например, имеются числовая, временная и денежная категории (только что упомянутый мною фасет time_put относится к временной категории). Я кратко описываю категории в данной главе, однако действительную пользу они приносят при осуществлении более изощренных действий, связанных с локализацией.

Каждая программа на C++ имеет, по крайней мере, одну локализацию, называемую глобальной локализацией (она часто реализуется как глобальный статический объект). По умолчанию это будет классическая локализация «С», пока вы не измените ее на что- нибудь другое. Один из конструкторов locale позволяет инстанцировать локализацию, предпочитаемую пользователем, хотя точное определение «предпочитаемой» пользователем локализации полностью зависит от реализации.

В большинстве случаев локализации используются при записи и чтении потоков. Это является основной темой настоящей главы.

13.1. Жесткое кодирование строк в коде Unicode

Проблема

Требуется в исходном файле жестко закодировать строки в коде Unicode, т.е. используя расширенный набор символов.

Решение

Начинайте строку с префикса L и затем вводите символы в своем редакторе исходных текстов, как вы это обычно делаете при написании строк, или используйте шестнадцатеричные значения, представляющие нужный вам символ в коде Unicode. Пример 13.1 демонстрирует оба способа кодирования таких строк.

Пример 13.1. Жесткое кодирование строк в коде Unicode

#include <iostream>

#include <fstream>

#include <string>

using namespace std;

int main() {

 // Создать несколько строк с символами кода Unicode

 wstring ws1 = L'Infinity: u221E';

 wstring ws2 = L'Euro: €'

 wchar_t w[] = L'Infinity: u221E';

 wofstream out('tmp\unicode.txt');

 out << ws2 << endl;

 wcout << ws2 << endl;

}

Обсуждение
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату