Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 221
Текст из файла (страница 221)
Чтобы выполнить сравнение, чувствительное к локализации, 0.4. Стандартные фасеты 1031 го!4 С'(соле! все!лез з1, соле! яьбпба з2, сопзс слог* и) Ь 1Ь=з1 ==зг; соле! слог* сз1 = з1.баса () т У поскольку сон!риге() работает с еааг(] сопя слог* сз2 = з2. баса ( ) с суредес'соИасе<слаг> Со!с сопл!Со!а е!оЬ = изе гасе!<Со!> (1оса!е() ) с У из текущей глобаль. локализации спс 10= е!оЬ .
со тра ге (сз1, сз1»з1 . з!ге ( ), сз2, ез2»з2 . я се ( ) ); сопл! Со!а ту соИ = изе Саве!<Со!> (1оса1е ("" ) ) ! У из предпочтитесьной лакал-ции си!!1 = ту соИ.сотраге(сзс,сз1»з!.з!ге(),сз2,сз2»з2.з!се() ) с соля Со!а соИ = изе Саве!<Со!> (1оса!е (и) ); УУ из !оса!е с именем и тс с2 = соИ . со тра ге (сз1, сз1»з1 .
з!се ( ), сз2, сз2«з2. ясе ( ) ); спс В = 1осасе ( ) (з1, з2); тс с4 = !оса!е ( " " ) (з1, з2) с тс !5 = !оса1е(и) (з1,з2) с ) УУ сравнение при текущей глобальной локализации И сравнение при предпочтительной локализации ((сравнение при локализации с именем п Здесь !О==!3, !1==!4 и !2==15. Нетрудно представить случаи, когда с2, !3 и !4 различаются.
Рассмотрим последовательность слов из немецкого словаря: Рса!еас, Иас, 4!сл, 4(ел!ел, Р(ел!ила По соглашению, сушествительные (и только) пишутся с заглавной буквы, но их порядок не зависит от регистра букв. Зависящая от регистра букв сортировка расположипа бы эти слова в таком порядке; Рса!елс, Иас, Рселсипе, 41сЬ, 4(ел!ел Буква а (а умляут) интерпретируется как «нечто вроде а», и поэтому она стоит раньше буквы с. Однако в большинстве символьных кодовых наборов числовое значение для а больше числового значения для с, то есть !пс(а) >спс(с), и на выходе простой сортировки на базе числовых значений будет: Рт!еьс, Рссьсипа, Р(ьс, осел, сисьсеи Написание функции сравнения, которая корректно упорядочивает данную последовательность слов точно по словарю, является интересным упражнением (вР.6[3)).
Функция Ьазй () вычисляет хзш-значение (в)7.6.2.3), которое требуется лля построения хзис-таблиц. Функция сгапзургт () производит из исходной строки некую строку, сравнение с которой третьих строк дает тот же результат, что и их сравнение с исходной строкой. Применение этой функции оптимизирует код, в котором некоторые строки сравниваются с одной и той же строкой. Это характерно для фрагментов, в которых, например, некоторая строка ишется во множестве других строк.
мы можем использовать функцию сотраге () фасета соИасе. С точки зрения простоты записи, лучше использовать сотраге() неявно, через функцию-операцию орегатог() () класса !оса!е (ВО.2.4). Например: Приложение () Локализация 1032 Функции сотраге(), Ьазй() и ггапзуогт(), объявленные в секции риЬИс, в своей реализации вызывают зашишенные виртуальные функции Ио сотраге (), Ио йазй () и Ио ггапц)огт (), соответственно; последние могут замеШаться в производных классах. Такая двухслойная стратегия позволяет разработчикам библиотек при реализации невиртуальных функций обеспечить некоторую обшую функциональность для всех вызовов в независимости от того, что будет реализовано в «г)о-функциях».
Использование виртуальных функций обеспечивает, хотя и несколько накладным образом, полиморфную природу фасетов. Во избежание лишних накладных расходов на эти вызовы 1оса1е может установить точную природу используемого фасета и кэшировать любые значения, необходимые для повышения производительности (5Р.2.2). Статический член Ы типа 1оса1е::Ы используется для идентификации фасета (5Р.З). Стандартные функции Ьазгасег и изе уасег полагаются на соответствие этих идентификаторов и фасетов (5Р.3.1).
Два фасета, предоставляюшие локализации один и тот же интерфейс и семантику, должны иметь одно и то же значение Ы Например, у соИаге<сйаг> и соИаге Ьупате<сйаг> эти идентификаторы одинаковые. И наоборот, два фасета, выполняющие разные функции по отношению к локализации, должны иметь разные Ы Например, у питрипсг<сйаг> и у пит ри1<сйал они разные (5Р.4.2). (з.4.1.1. Именованные фасеты сравнения Фасет соИаге Ьупате является для конкретной локализации вариацией соИаге с именем, заданным строковым аргументом конструктора: ге»ар!аге<с1ат Сй> с1азз зЫ:: сапоге Ьупате: риЬИс содаге<СЬ> риЫ1с: зуреееГЬаз(с вицпя<СЬ> ззг1пд гуре; У конструирование из именованной локализации: ехрпс11 сойа<е Ьупате(сопл( сйаг*, зйе 1 г = 0) гЗ внимание: ни нового )ф ни навык функций ргогесгед: -со11аге Ьулате [) г II внимание: рго)ес)ей деструктор ь' замещаем виртуальные функции сойаге<СЬ>: 1лг Ео сотраге(солт СЬ* Ь, солт СЬ* е, сопле СЬ* ЬЗ, сопл) СЬ* е2) салаг ззг1пд гуре ео ггапззогт (сопл) СЬ* Ь, солт Сй* е) соптг 1оле ~!о Ьазй(соле( Сй* Ь, солт СЬ* е) сопвгг Таким образом, фасетом соИаге Ьупате можно пользоваться для извлечения фасета соИаге из локализации, именованной в рамках системной среды выполнения программы (5гз.4).
Очевидным способом хранения фасетов в среде выполнения является запись необходимых данных в файл на диске. Менее гибкой альтернативой будет представление фасета в виде кода и данных в фасете с суффиксом Ьуиазпе. 1ОЗЗ 0.4. Стандартные фасеты Класс соИаге Ьуиате<сйаг> является примером фасета, у которого нет собственного Ы (513.3). В рамках 1оса1е фасеты сойа!е Ьупате< СЬ> и соИаге< СЬ> взаимозаменяемы.
Фасеты соИаге и соИаге Ьупате для одной и той же локализации различаются лишь дополнительным конструктором фасета содаге Ьупате, а также его семантикой. Отметим, что деструктор у соИаге Ьупате защищенный. Это означает, что нельзя определить локальные (в функции) объекты типа соИаге Ьуиате: »оЫ)'( ) ( соИаге букете<сдпг> ту соИ("") г р,.. УУ еггог: невозможно уничтожить ту со!! 0.4.2. Ввод и вывод чисел Вывод чисел выполняется фасетом пит ри! посредством записи в буфер потока (521.6.4).
Ввод чисел выполняется фасетом пит ае! путем чтения из буфера потока. Формат, используемый фасетами иит ри! и пит аег, задается «фасетом пунктуации чисел» вЂ” питриис!. О.4.2.1. Пунктуация чисел Фасет питрипс! определяет формат ввода/вывода встроенных типов, таких как Ьоо1, 1п! и ИоиЫе; !етр1аге<с1ат СЬ > с(ат зЫ:: питрипсг: риЫЫ!оса(е::(асе! ( риЫ«с: (уреч!е~ СЬ сдпг (уре; (уре«(е!'Ьаз(с зазпе<СЬ> згг!пе (урез ехрвсв питрипс! (з!се ! г = 0) ч СЬ аес(та! ро(п!() сапог; У '.'в с!азлсВ СЬ своизапаз зер() сопзз; УУ ','в с!азлсВ за!ля егоир!пя() сопзгг УУ "" в с1азлс() — значит, что нет группировки згыпя (уре пиепате() сопзг; УУ»оие» в с!озз!с() з(г!пе (уреза!зените () сопзгч р 7а!зе" в с!озлс() згаг!с !оса1е:: Ы Ыг Р обьект идентификации фосета (ЗР2, ЗР.З, ЗР.З.!) ргогесге4: -питринс! ( ) ! г7 виртуальные з!о "-функции (см.
зР.4.!) Это отражает взгляд на то, что контексты локализации и фасеты лучше определять где-нибудь на более высоком уровне, чтобы они могли оказывать влияние на более обширные фрагменты программ. Например, установка глобального контекста (513.2.3) или прикрепление контекста локализации к потоку (521.6.3, 92.1). Но при необходимости, мы можем наследовать от соИа!е Ьупате класс с открытым деструктором и создавать локальные обьекты такого класса. 1034 Приложение О. Локализация Символы строки, возврашаемые функцией Вгоир!п8 (), читаются как последовательность небольших целых значений, каждое из которых идентифицирует число цифр в группе.
Символ с номером 0 соответствует самой правой группе (то есть наименее значимым цифрам), символ с номером 1 — группу слева от предыдущей и т.д. Таким образом, "(004(002)003" описывает формат чисел вида 123-45-6789 (при условии, что в качестве разделителя используется знак ьд). При необходимости последнее числовое значение в образце группировки может быть повторено. В нашем примере ")003п эквивалентно, например, ")003)003)003". Само название функции гйоиеап0е еер() (разделение тысяч), возврашаюшей символ разделения, говорит о том, что основное предназначение группировки заключается в том, чтобы представить большие числа в более читаемой форме. Функции Вгоир!п8() и 1ЬоихиеЬ еер () определяют формат и для ввода, и для вывода целых чисел. Они также определяют формат целой части чисел с плавающей запятой, но не цифр после Вес!та! ро1иг() .
Можно определить новый стиль пунктуации чисел, создавая производный от иитриисг класс. Например, я могу определить фасет Му риис! для записи целых значений тройками цифр с пробелом между ними, и для записи чисел с плавающей запятой с использованием запятой в Европейском стиле, отделяющей дробную часть от целой части числа: с1ат Му рипсьн риЫ)с в!4:: питрилсг<слаг> риЫ!с: (уребеу слог сьаг (урез гуребе1' в(гшВ вгггп8 (уре; ехр11с!! Му риис!(в!ее ! г = О): вИ::питрилсг<сбаг> (г) () рго!ес!е4: слог 4о 4ес!та! ро!т() солт (ге!игл ', '; ) В залатал сбаг 4о Оюивапбв вар() соле! (гетгп ' '; ) Улробел в!Ып8 4о Вгоир(пл () солт (ге!игп "~ВОЗ"; ) р 3 цифровые группы го!41'( ) ( сои! «ве(ргес!«оп (4) « фхе4; сои(« "в!у1е А: " «!2345678« " *** " «1234.5678 « ' ~п'; !оса1е 1ос (1осаге (), пеп Му риис!); сои!. нпбие (!ос); сои!« "«у)е В: " «12345678« " *** " «1234.