致力於在現代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 的抽象。目前來看,前途光明。