簡體   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