Шаг 533.
Библиотека STL.
Интернационализация. Фацеты

    На этом шаге мы рассмотрим фацеты и их использование.

    На функциональном уровне локальный контекст делится на несколько специальных объектов. Объект, обеспечивающий работу некоторого аспекта интернационализации, называется фацетом. Это означает, что объект локального контекста может рассматриваться как контейнер для различных фацетов. Для обращения к некоторому аспекту локального контекста тип соответствующего фацета передается в аргументе шаблонной функции use_facet(). Например, следующее выражение обращается к фацету типа numpunct для типа символов char объекта локального контекста lос:

  std::use_facet<std::nurnpunct<char> >(loc)

    Каждый тип фацета определяется в виде класса, предоставляющего определенные сервисы. Например, тип фацета numpunct предоставляет сервис форматирования числовых и логических величин. Так, следующее выражение возвращает строку, используемую для представления true в локальном контексте lос:

  std::use_facet<std::numpunct<char> >(loc),truename()

    В таблице 1 приведена сводка фацетов, поддерживаемых стандартной библиотекой C++. Фацеты делятся на категории, используемые некоторыми конструкторами для создания новых объектов локальных контекстов на основании комбинации других объектов.

Таблица 1. Типы фацетов, определенные в стандартной библиотеке C++
Категория Тип фацета Использование
numeric num_get<>() Ввод числовых данных
num_put<>() Вывод числовых данных
numpunct<>() Символы, используемые при числовом вводе-выводе
time time_get<>() Ввод даты и времени
time_put<>() Вывод даты и времени
monetary money_get<>() Ввод денежных величин
money_put<>() Вывод денежных величин
moneypunct<>() Символы, используемые при вводе-выводе денежных величин
ctype ctype<>() Информация о символах (toupper(), lsupper())
codecvt<>() Преобразование между кодировками
collate collate<>() Контекстное сравнение строк
messages messages<>() Чтение строковых сообщений

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

class germanBoolNames : public std::numpunct_byname<char> {
  public:
    germanBoolNames (const char *name)
      : std::numpunct_byname<char>(name) {
    }
  protected:
    virtual std::string do_truename () const {
        return "wahr";
    }
    virtual std::string do_falsename () const {
        return "falsch";
    }
};

    Класс germanBoolNames объявлен производным от класса numpunct_byname, определенного в стандартной библиотеке C++. Этот класс определяет параметры локального контекста, применяемые при числовом форматировании. Использование базового класса numpunct_byname, вместо numpunct позволяет модифицировать функции класса, которые не переопределяются явным образом. Значения, возвращаемые этими функциями, зависят от имени, переданного в аргументе конструктора. Если бы в качестве базового использовался класс numpunct, то поведение этих функций было бы жестко фиксированным. Класс germanBoolNames переопределяет две функции, определяющие текстовое представление значений true и false.

    Чтобы использовать этот фацет в локальном контексте, необходимо создать новый объект локального контекста при помощи специального конструктора класса locale. В первом аргументе этого конструктора передается объект локального контекста, а во втором - указатель на фацет. Созданный локальный контекст идентичен первому аргументу во всем, кроме фацета, переданного во втором аргументе. Заданный фацет устанавливается в созданном объекте контекста после копирования первого аргумента:

  std::locale loc (std::locale(""), new germanBoolNames(""));

    Подвыражение new создает фацет, устанавливаемый в новом локальном контексте. Таким образом, фацет регистрируется в loc для создания специализированной версии lоса1е(""). Поскольку прямая модификация объектов локального контекста невозможна, для установки нового фацета в локальном контексте придется создать новый объект локального контекста. Этот новый объект используется так же, как любой другой объект локального контекста. Например, рассмотрим такой фрагмент:

  std::cout.imbue(loc);
  std::cout << std::boolalpha << true << std::endl;

    Этот фрагмент выдает следующий результат:

  wahr

    Вы также можете создать абсолютно новый фацет. В этом случае функция has_ facet() позволяет узнать, был ли этот новый фацет зарегистрирован для заданного объекта локального контекста.

    На следующем шаге мы рассмотрим строение объекта локального контекста.




Предыдущий шаг Содержание Следующий шаг