[英]Range-based for loop with auto specifier combined with static_cast
想象我有一個std::vector
std::string
的std::vector
,我想在基於范圍的 for 循環std::string_view
那些std::string
轉換為std::string_view
:
auto v = std::vector<std::string>{"abc", "def", "ghi"};
for (std::string_view sv : v) {
// do something with string_view
}
上面的代碼是完全有效的,但我想保留auto
說明符來做到這一點,如何在一行基於范圍的 for 循環中執行static_cast
像這樣? 似乎 C++20 ranges
可以以簡潔的方式做到這一點,有人可以舉個例子嗎?
for (auto sv : v | static_cast<std::string_view>) {
// do something with std::string_view
}
並不是說這是一個好主意,但這可能是一個更通用的轉換概念(和一個邪惡的 lambda 技巧)的有用示例:
for(auto sv : v |
views::transform([](std::string_view x) {return x;})) …
正如@Elijay 評論的那樣,您可以簡單地創建一個新的string_view
vector
:
for (auto sv : vector<string_view>(v.begin(), v.end()))
但這首先違背了使用string_view
的全部目的:避免復制。
正如下面所評論的,它也有點違背了auto
的全部目的:避免不必要地重述類型信息。 這里是第一次引入該類型,因此必須明確說明。 為什么不直接在前面?
不那么冗長string_view
預期使用string_view
是您開始的地方:
for (string_view sv : v)
你可以這樣做:
#include <string>
#include <vector>
#include <iostream>
#include <string_view>
int main() {
auto v = std::vector<std::string>{"abc", "def", "ghi"};
for (auto sv : std::vector<std::string_view>(v.begin(), v.end())) {
// use sv ...
}
}
但是請注意,根本不建議創建一個全新的向量。 它再次分配內存並導致大量不必要的開銷。 此外,無論如何您都必須在某處拼寫類型,因此auto
在這里根本沒有任何優勢。 正確的事情TM是明確指定類型名稱而不是使用auto
。
迭代器是一個很好的定制點,不幸的是它需要一些樣板:
#include <vector>
#include <iostream>
#include <string_view>
template <typename T>
struct container_view {
const T& container;
container_view(const T& t) : container(t) {}
struct iterator{
typename T::const_iterator base;
iterator(const typename T::const_iterator& it) : base(it) {}
bool operator!=(const iterator& other) { return base != other.base; }
iterator& operator++() { ++base; return *this; }
std::string_view operator*() { return {*base}; }
// ^--- string_view
};
iterator begin() { return {container.begin()};}
iterator end() { return {container.end()};}
};
int main (){
auto v = std::vector<std::string>{"abc", "def", "ghi"};
// v--- auto
for (auto sv : container_view(v)) {
std::cout << sv << '\n';
}
}
可以說更多/更少簡潔。 意見會有所不同。
#include <vector>
#include <string_view>
#include <string>
#include <iostream>
#include <range/v3/view/transform.hpp>
int main()
{
auto v = std::vector<std::string>{"abc", "def", "ghi"};
using namespace ranges;
auto as_string_view = views::transform([](auto&& x) { return std::string_view(x); });
for (auto sv : v | as_string_view) {
std::cout << sv << '\n';
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.