致力于在现代C++中提供Python的编程体验。这个创建在两个关键的基础上python
c++ 11/14/17 提供了从 auto 到 structure binding 的语法便利c++
https://ericniebler.github.io... 提供的 range 抽象git
可是 python 体验是创建在语言内建的大量方便函数的基础之上的。而 Modern C++ 还缺乏大量使用起来方便的库。github
咱们今天要来解决的第一个问题是如何在C++中表达字符串。选择一个字符串的实现主要有三方面的考虑:编程
是值对象仍是引用对象:std::string
是值对象,std::string_view
是引用对象。值对象即使用上了全部的优化(stack分配内存,ref counted cow)仍然是有开销的。在该使用应用的地方,仍然应该使用引用。api
值对象的内存管理。folly::fbstring
就比 std::string
更好地利用了内存数组
支持 unicode:不该该把字符串简单当作一个char数组app
市面上几乎全部的string抽象对unicode支持都很差。我但愿的是相似u'中文字符'
这样的使用体验。c++ 11/14/17 在unicode支持方面支持得很是有限:函数
虽然引入了char16_t 和 char32_t,可是你觉得字符串就是 vector<char32_t> 就太天真了。使用的时候须要各类字符转换到char32_t不说,并且locale竟然不支持char32_t,意味着基本的toupper都没法实现优化
regex 不支持 unicode,.
是没法匹配一个完整的code point 的
https://github.com/CaptainCro... 这个封装是最接近的,可是不是基于 range-v3 的。
目前的我实现的代码在:https://github.com/taowen/pyt...
定义一个字符串常量
auto str = U8("中文字符");
U8是一个宏,能够保证u8""
这样字符串声明(c++ 编译器支持的 utf8 编码),同时额外作的工做是让构造出来的字符串和普通的字符串类型不兼容,避免误用。也就是 string != unicode 。这个就至关于
str = u'中文字符'
取得字符串长度
CHECK(2 == (U8("中文") | pyn::len));
这个就至关于
len(u'中文')
若是不喜欢 |
的调用语法,也能够用普通的函数
pyn::len(U8("中文"));
首字母大写
CHECK(U8("Hello") == (U8("hello") | utf8::capitalize | utf8::to_text));
注意这里 capitalize 并不会当即返回一个新的字符串(分配一个新的内存空间,而后拷贝字符),而是返回了一个相似python generator的东西。在 to_text
的时候才会分配内存,进行计算。默认 to_text
返回的字符串类型是 utf8::Text
底层存储是 folly::fbstring
。
这里定义的字符串并不能直接遍历或者下标访问,由于在unicode中什么一个“character“是有歧义的,把字符串当作一个数组是一个过期的想法(即使是16位的char)。字符串就没有常量时间可随机访问这么一说。若是须要遍历,须要这么写
auto chars = std::vector<char>{}; for (auto c : U8("abc") | utf8::code_units) { chars.push_back(c); } CHECK((std::vector<char>{'a', 'b', 'c'}) == chars);
这个取得的是code unit,在非ascii范围内的字符会读取不完整。
auto chars = std::vector<utf8::TextView>{}; for (auto c : U8("中文") | utf8::code_points) { chars.push_back(c); } CHECK((std::vector<utf8::TextView>{U8("中"), U8("文")}) == chars);
这里的遍历就相似
chars = [] for c in u'中文': chars.append(c) [u'中', u'文'] == c
咱们这里干的事情相似于python 2.7 里 string/unicode 两种类型的区分。咱们须要一种存储上是string(utf8编码),可是使用起来相似 unicode 的抽象。目前来看,前途光明。