14 国际化
14.1 不同的字符编码
1、多字节表示法:字符所用的byte个数是可变的;宽字符表示法:字符所用byte数目恒定。
2、字符特性
namespace{tempalte <class charT> struct char_traits{...};}
template<> struct char_traits<char>{
typedef char char_type;
typedef int int_type;
typedef streampos pos_type;
typedef streamoff off_type;
typedef mbstate_t state_type;
static int eof(){return EOF;}
static int not_eof(const int& i){return i!=EOF?i:!EOF;}
...
}
3、特殊字符国际化:成员函数widen()和narrow()。
14.2 Locale的概念
1、std::loacle::classic();等价于std::locale("C");经典的C locale。
2、facet:locale对象就是facet的容器。std::use_facet<std::numpunct<char> >(loc)便可取得loc所辖的“字符型别为char”的facet numpunct。
14.3 locale细部讨论——<locale>
注意:上图中combine()是成员函数模板,在调用时需要显示加上template。而下图中的has_facet()是全局模板函数,所以不必加上关键词template。
注意1:如果一个locale是另一个locale的副本,或两个locale名字相同,则两个locale被认为相同。
注意2:loc(str1, str2)是对operator()的重载,就是仿函数的行为,因此可以这样使用:
std::vector<std::string> v; ...; std::sort(v.begin(), v.end(), locale("de_DE")); //运用German locale所定义的规格,对一个容纳字符串的vector进行排序。
14.4 facet细部讨论
标准facet的所有成员函数声明为const(因为use_facet()返回一个reference指向constant facet);所有public函数都不是虚函数,而是将调用委托给一个protected虚函数(模板方法设计模式)。
大多数标准facet都定义了一个“by_name”版本,std::numpunct_byname("de_DE");//根据一个具名的locale产生一个facet。
字符的分类和转换——ctype和codecvt
ctype主要用于字符分类,此外还提供大小写转换;codecvt用来在不同编码之间进行字符转换。
//将数字字符由char转换为wchar_t
std::locale loc;
char narrow[] = "0123456789";
wchar_t wide[10];
std::use_facet<std::ctype<wchar_t> >(loc).widen(narrow, narrow+10, wide);
std::islower(c, loc);等价于std::use_facet<std::ctype<char> >(loc).is(std::ctype_base::lower, c);
注意:这些全局函数和同名但只有一个参数 的C函数对应。这些定义于<ctype>和<ctype.h>的C函数总是使用当前的全局C locale,如std::isdigit(c)。