繁体   English   中英

带有自动说明符和 static_cast 的基于范围的 for 循环

[英]Range-based for loop with auto specifier combined with static_cast

想象我有一个std::vector std::stringstd::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM