[英]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.