typedef void (*WorkerFunPtr)(const std::string&);
Это создает тип WorkerFunPtr, который является указателем на функцию, принимающую по ссылке аргумент типа stringи возвращающую тип void. После этого я создал шаблон класса Adapter. Он обеспечивает инстанцирование динамического функтора. Обратите внимание на конструктор:
template
typename ParamT>
struct Adapter {
Adapter(FunT f, ParamT& p) : f_(f), p_(&p) {}
// ...
Конструктор только инициализирует два члена, которые могут быть любого типа, но нам нужно, чтобы это был указатель на функцию и некоторый параметр pлюбого типа. Ради повышения эффективности я сохраняю адрес параметра, а не его значение.
Теперь рассмотрим следующую строку главного потока.
boost::thread thr1(Adapter(worker, s1))
Аргумент конструктора thr1представляет собой реализацию шаблона класса Adapter, использующую в качестве параметров два типа WorkerFunPtrи std::string. Это именно те два типа, которые являются членами адаптера f_и p_. Наконец, Adapterперегружает operator(), поэтому он может вызываться как функция. Его вызов означает просто выполнение следующей функции.
f_(*p_);
Применяя шаблон класса Adapter, можно передавать аргументы функциям потока, причем делается это за счет лишь небольшого усложнения синтаксиса. Если требуется передавать еще один аргумент, просто добавьте дополнительный тип и переменную-член в шаблон Adapter. Этот подход привлекателен тем, что позволяет создавать набор шаблонов классов обобщенного адаптера и использовать их в различных контекстах.
Глава 13
Интернационализация
В данной главе приводятся решения некоторых задач, которые обычно возникают при интернационализации программ С++. Обеспечение возможности работы программы в различных регионах (это обычно называется локализацией ), как правило, требует решения двух задач: форматирования строк, воспринимаемых пользователем, в соответствии с местными соглашениями (например, даты, времени, денежных сумм и чисел) и обеспечения работы с различными символьными наборами. В настоящей главе рассматривается в основном первая проблема и только кратко вторая, потому что имеется немного возможностей по стандартизации поддержки различных символьных наборов из-за того, что такая поддержка во многом зависит от реализации.
Большая часть программного обеспечения будет работать в странах, отличных от той, где они были написаны. Для поддержки этой практики стандартная библиотека C++ имеет несколько средств, способствующих написанию программного кода, предназначенного для работы в различных странах. Однако они спроектированы не так. как многие другие средства стандартной библиотеки, например строки, файловый ввод-вывод, контейнеры, алгоритмы и т.п. Например, класс, представляющий локализацию, имеет имя localeи содержится в заголовочном файле саlе>. Класс localeпредоставляет средства для записи и чтения потоков с применением специфичного для данной местности форматирования и получения таких сведений о локализации, как, например, ее символ валюты или формат даты. Однако стандартом предусматривается обеспечение только одной локализации, и этой локализацией является «C»-локализация, или классическая локализация. Классическая локализация использует стандарт ANSI С: принятые в американском варианте английского языка соглашения по форматированию и 7-битовой код ASCII. И от реализации зависит, будут ли обеспечены экземпляры locale для других языков и регионов.
Заголовочный файл имеет три основные части. Во-первых, это класс locale(локализация). Он инкапсулирует все поддерживаемые в C++ особенности локализованного поведения и обеспечивает точки входа для получения различной информации о локализации, необходимой для выполнения локализованного форматирования. Во-вторых, самыми маленькими элементами локализации и конкретными классами, с которыми вы будете работать, являются классы, называемые фасетами (facets) . Примером фасета является, например, класс time_put, предназначенный для записи даты в поток. В-третьих, каждый фасет принадлежит к некоторой категории, которая объединяет связанные фасеты в одну группу. Например, имеются числовая, временная и денежная категории (только что упомянутый мною фасет time_putотносится к временной категории). Я кратко описываю категории в данной главе, однако действительную пользу они приносят при осуществлении более изощренных действий, связанных с локализацией.
Читать дальше