标签: std-ranges

什么是 std::views::counted?

https://en.cppreference.com/w/cpp/ranges上,std::views::counted列在范围适配器部分中。但是,它没有标记为范围适配器对象。

我想这就是为什么我不能使用管道运算符编写的原因,例如:

std::vector<size_t> vec = {1, 2, 3, 4, 5};
auto view = vec | std::ranges::counted(... ; // does not compile
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  • 什么是std::ranges::counted?为什么它列在范围适配器部分中?
  • 有哪些用例?与使用takedrop相比有哪些优点?

c++ std c++20 std-ranges

3
推荐指数
1
解决办法
691
查看次数

缓存视图对象内部会导致UB?

#include <iostream>
#include <vector>
#include <ranges>

int main()
{
    std::vector<int> ints {1, 2, 3, 4, 5};
    auto isEven = [] (const auto& element)
    {
        return element % 2 == 0;
    };
    auto even = ints | std::views::filter(isEven);
    for (auto& element : even)
    {
        ++element;
    }
    for (const auto& element : ints)
    {
        std::cout << element << "\n";
    }
    std::cout << "\n\n";
    
    // Interesting things start further...
    for (auto& element : even)
    {
        ++element;
    }
    for (const auto& element : ints) …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

3
推荐指数
2
解决办法
187
查看次数

std::views::istream 与 std::views::take

我用 g++ 12.2.1 编译了以下代码:

#include <iostream>
#include <ranges>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
    std::vector<int> vi;
    std::ranges::copy(std::views::istream<int>(std::cin) | std::views::take(3), std::back_inserter(vi));
    for (auto i : vi)
        std::cout << i << ' ';
}
Run Code Online (Sandbox Code Playgroud)

输入:

1 2 3
4
Run Code Online (Sandbox Code Playgroud)

输出:1 2 3

为什么我必须输入 4 个数字而不是 3 个数字并丢弃最后一个数字?怎么解决?

c++ c++20 std-ranges

3
推荐指数
1
解决办法
103
查看次数

在基于范围的循环中删除地图元素

我想根据某些条件从地图中删除一些元素:

#include <unordered_map>
#include <ranges>
#include <iostream>

int main() {

    std::unordered_map<int, int> numbers = {{1,2}, {2,1}, {3,2}, {4,5}};

    auto even = [](auto entry){return entry.second %2 == 0;};
    for(auto& [key, val] : numbers | std::views::filter(even)) {
        numbers.erase(val);
    }

    for(auto& [key, val] : numbers) {
        std::cout << key << " " << val << "\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

但似乎我正在使基于范围的循环所需的迭代器无效:

4 5
3 2
1 2
Run Code Online (Sandbox Code Playgroud)

我知道如何使用迭代器显式地执行此操作,但是是否有一种基于范围的简洁方法来删除基于过滤器的元素?

c++ unordered-map std-ranges range-based-loop

3
推荐指数
1
解决办法
292
查看次数

使用 std::views::chunk 编译此代码时,为什么会出现错误:无法分解无法访问的成员?

此代码可以正确编译并运行:

\n
#include <ranges>\n#include <iostream>\n\nint main() {\n    const auto r = std::views::iota(\'a\', static_cast<char>(\'g\' + 1));\n\n    for(const auto& [start, end] : r | std::views::chunk(3u)) {\n        for(auto it = start; it != end; ++it) {\n            std::cout << *it << " ";\n        }\n        std::cout << "\\n";\n    }\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

其输出为:

\n
a b c \nd e f \ng \n
Run Code Online (Sandbox Code Playgroud)\n

如果我将定义更改r如下:

\n
a b c \nd e f \ng \n
Run Code Online (Sandbox Code Playgroud)\n

该代码无法编译。GCC 13 发出以下错误:

\n
chunk.cpp:13:21: error: cannot decompose inaccessible …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges c++23

3
推荐指数
1
解决办法
362
查看次数

为什么transform_view不是bored_range?

对于std::ranges,为什么transform_view不是bored_range?这是一个简单的示例: https: //godbolt.org/z/14K8Y1xMe及以下:

#include <ranges>

void foo() {
    auto i = std::ranges::views::iota(10);
    auto t = i | std::ranges::views::transform([](auto v) {return v;});
    static_assert(std::ranges::borrowed_range<decltype(i)>);
    static_assert(std::ranges::borrowed_range<decltype(t)>);
}
Run Code Online (Sandbox Code Playgroud)

我检查过该基数是借用的范围。是不是功能有问题?文档没有说:https://en.cppreference.com/w/cpp/ranges/transform_view

c++ std-ranges

3
推荐指数
1
解决办法
117
查看次数

范围管道删除用于格式化样式的 typedef

使用 C++23,我们可以漂亮地打印范围,目前在{fmt}. 例如,std::set格式为{},而序列容器如std::vector格式为[]。在内部,formatter类模板根据嵌套 typedef 的存在key_typestd::set有或std::vector没有)进行调度。

通过管道将 astd::set插入任何类型view都会删除key_typetypedef 并将其漂亮地打印为std::vector.

#include <ranges>
#include <set>
#include <fmt/ranges.h>

int main()
{
    auto s = std::set<int>({ 2, 3, 5, 7 });

    fmt::println("{}", s);                                              // nice, formats as { 2, 3, 5, 7 }
    fmt::println("{}", s | std::views::reverse);                        // meh, now uses [] instead of {}
    fmt::println("{}", s | std::views::reverse …
Run Code Online (Sandbox Code Playgroud)

c++ pipeline fmt std-ranges c++23

3
推荐指数
1
解决办法
165
查看次数

使用 C++ 范围生成唯一的随机数

我一直在尝试一些只是为了好玩,但我偶然发现了以下方法的问题。问题是我在生成的范围内两次得到零值。我错过了什么?我没有正确使用范围还是与 unordered_set 有关?

    auto rng = 
    std::views::iota(0) | 
    std::views::transform([](size_t){ return rand() % 26; }) |
    std::views::filter([u = std::unordered_set<size_t>()](size_t i) mutable { return !u.emplace(i).second; }) |
    std::views::take(15);

    for (auto&& x : rng) { 
        std::cout << x << std::endl;
    }
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

3
推荐指数
1
解决办法
93
查看次数

当匹配计数大于某个阈值时,我可以使用 C++20 范围来中断吗?

考虑以下预范围代码:

std::vector<int> v(1000*1000);
bool count_gt_5_v1(int val){
    return std::count(v.begin(), v.end(), val)>5;
}
Run Code Online (Sandbox Code Playgroud)

它看起来比原始循环更好,但如果 val 在 v 中非常常见,它可能会非常低效。

有什么方法可以使用 C++20 范围,以便在我遇到 val 6 次后停止迭代。换句话说,我正在寻找一种在我的条件满足时引入休息的方法。我有这个可憎的东西,这似乎有效,但它比原始 for 循环丑得多。

bool count_gt_5_v2(int val){
    int cnt=0;
    auto span = std::ranges::views::take_while(v,[&cnt, &val]
    (const auto elem)
    {
        cnt+=elem==val; 
        return cnt<6;
    });
    std::ranges::distance(span);
    return cnt==6;
}
Run Code Online (Sandbox Code Playgroud)

完整代码链接:https : //godbolt.org/z/86djdK

c++ c++20 std-ranges

2
推荐指数
1
解决办法
96
查看次数

定义transform_view?::iterator的iterator_category的问题?

该标准在[range.adaptors] 中定义了各种范围适配器,其中一些具有自己的迭代器类型。

为了标准化iterator_category这些迭代器,标准还规定了它们是如何定义的。例如,在[range.transform.iterator-2] 中iterator_categoryoftransform_view?::?iterator定义如下:

成员typedef-name iterator_­category当且仅当Basemodels 定义forward_­range。在那种情况下, iterator?::?iterator_­category定义如下:让C表示类型iterator_­traits<iterator_­t<Base>>?::?iterator_­category

如果is_­lvalue_­reference_­v<invoke_­result_­t<F&, range_­reference_­t<Base>>>true,那么

  • 如果C模型 derived_­from<contiguous_­iterator_­tag>,iterator_­category 表示random_­access_­iterator_­tag;

  • 否则,iterator_­category表示C

否则,iterator_­category表示input_­iterator_­tag

但是这个定义似乎有一些问题,考虑以下情况

vector v{1, 2, 3, 4, 5};
auto r = views::iota(0, 5) | 
         views::transform([&](int i) -> int& { return v[i]; });

using I = …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

2
推荐指数
1
解决办法
86
查看次数

标签 统计

c++ ×10

std-ranges ×10

c++20 ×7

c++23 ×2

fmt ×1

pipeline ×1

range-based-loop ×1

std ×1

unordered-map ×1