我試圖用C 20(MSVC on visual studio 19 v142, c latest)將一個向量轉換為一個字串并加入。
std::vector<std::string> strings = { "1s"/span>,"2s"/span> };
auto view1 = strings | std::views::transform([] (std:: string num) {return std::format("{}", num); }); // okay
auto view2 = strings | std::views::join; // ok
auto view3 = strings | std::views::transform([](std::string num) {return std::format("{}" /span>, num); }) | std::views::join; //編譯器錯誤。
//error C2678: 二進制'|': 沒有找到運算子,該運算子的左側運算元型別為'std::ranges_view<std::ref_view<std::vector<std::string<std::string>>,_Ty>'
我知道我可以在range-v3中用actions優雅地完成它,但我不應該使用它。
有沒有一種方法可以做到這一點,只需使用C 20標準庫?
uj5u.com熱心網友回復:
在views::join的最初設計中,它不只是連接任何范圍的范圍,它必須是對范圍的參考范圍。
這樣做了:
auto view2 = strings | views::join; // okay
因為strings是string&的一個范圍(它是對一個范圍的參考)。
但這并不是:
auto view3 = strings | views::transform( [](std::string num) {
return std::format("{}"/span>, num)
})
| views::join; //編譯器錯誤。
因為現在我們join了一個范圍的字串(特別是prvalue字串,這是你的函式回傳的)。這違反了約束條件。range-v3的views::join有同樣的約束條件。
然而,能夠做到這一點是一個相當常見的用例。因此,最近針對C 20的一個缺陷是改變了
views::join的設計,允許它連接任何范圍的范圍。這就是P2328。libstdc (gcc的標準庫)已經實作了這一點,MSVC還沒有,range-v3也沒有(盡管我有一個PR開放)。因此,C 20的官方答案是:你所做的是正確的,你的庫只是還沒有實作它。。
現在,range-v3的答案是引入一個快取層:
auto view3 = strings | rv::transform([] (std::string num) {
return std::format("{}"/span>, num)
})
| rv::cache1
| rv::join;
cache1所做的是一次快取一個元素,它將我們的pr值string的范圍變成l值string的范圍,這樣join就可以成功地加入它。P2328的設計基本上是在內部將其納入join本身,這樣你就不必手動操作了。但在這之前,你可以使用range-v3來完成上述作業。C 20中沒有cache1,C 23中也不會有。
或者你可以使用Casey的黑客。但也不要這樣做。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/331853.html
標籤:
下一篇:用鍵盤上的Tab鍵洗掉選擇按鈕
