标签: std-ranges

clang++-12 找不到库范围

我正在测试 C++ 20 的范围,这是我的main.cpp

#include <ranges>
#include <iostream>

int main()
{
    auto const ints = {0,1,2,3,4,5};
    auto even = [](int i) { return 0 == i % 2; };
    auto square = [](int i) { return i * i; };

    for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
        std::cout << i << ' ';
    }

    std::cout << '\n';
}

Run Code Online (Sandbox Code Playgroud)

编译它clang++-12但找不到“范围”:

$ clang++-12 --version
Ubuntu clang version 12.0.1-++20210525082622+328a6ec95532-1~exp1~20210525063352.95
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin …
Run Code Online (Sandbox Code Playgroud)

c++ clang c++20 std-ranges

10
推荐指数
0
解决办法
5599
查看次数

我应该怎么做才能让我的容器与范围一起工作?

我有一个简单的容器:

template <class T, class Allocator = std::allocator<T>>
class ring
{
public:

    using value_type = T;
    using allocator_type = Allocator;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using reference = T &;
    using const_reference = const T &;
    using pointer = T *;
    using const_pointer = const T *;

private:

    template <class E>
    class ring_iterator
    {
    public:

        using iterator_category = std::random_access_iterator_tag;
        using value_type = E;
        using difference_type = std::ptrdiff_t;
        using reference = E &;
        using pointer = E *; …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

10
推荐指数
1
解决办法
1142
查看次数

为什么 std::common_iterator 只是 std::forward_iterator?

C++20 引入了std::common_iterator能够将元素的非公共范围(迭代器和哨兵的类型不同)表示为公共范围(它们相同)的 a ,其概要定义为:

template<input_­or_­output_­iterator I, sentinel_­for<I> S>
    requires (!same_­as<I, S> && copyable<I>)
class common_iterator {
  // ...
 private:
  variant<I, S> v_;   // exposition only
};
Run Code Online (Sandbox Code Playgroud)

它对于与期望范围的开始和结束具有相同类型的遗留代码进行交互非常有用。

[iterators.common#common.iter.types-1.1] 中,其iterator_­concept定义为:

iterator_­concept表示forward_­iterator_­tag如果I模型 forward_­iterator;否则表示input_­iterator_­tag

为什么common_iterator最多只能是 a forward_iterator,而不能完全定义其iterator_concept基于I's iterator_category?例如,如果Irandom_asscess_iterator,则common_iterator<I, S>random_asscess_iterator,依此类推。

看来,这是因为技术上是可行的common_iterator只是使用std::variant类型为擦除IS

考虑以下(Godbolt): …

c++ iterator range-v3 c++20 std-ranges

9
推荐指数
2
解决办法
257
查看次数

使用 c++20 范围删除最后一个元素的最佳方法是什么

有没有比反转两次更好的方法来使用 c++20 范围删除容器中的最后一个元素?

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

int main()
{
    std::vector<int> foo{1, 2, 3, 4, 5, 6};

    for (const auto& d: foo | std::ranges::views::reverse 
                            | std::ranges::views::drop(1) 
                            | std::ranges::views::reverse)
    {
        std::cout << d << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

9
推荐指数
2
解决办法
1816
查看次数

立管|什么是立管 c++20 和范围上下文中的平均值

有些用法|看起来更像函数管道或链接,而不是按位或,与 c++20 范围结合使用。像:

#include <ranges>
#include <vector>

template<typename T>
std::vector<T> square_vector(const std::vector<T> &some_vector) {
    auto result = some_vector | std::views::transform([](T x){ return x*x; };
    return {result.begin(), result.end()};
}
Run Code Online (Sandbox Code Playgroud)

显然,该|运算符不是按照通常意义上的按位或来使用的。它从什么时候开始工作,在什么类型的函数/对象上工作?这些像常规视图吗?有哪些注意事项?

c++ c++20 std-ranges

9
推荐指数
1
解决办法
2693
查看次数

如何在向量上使用 std::views::transform ?

我正在尝试将视图创建为转换类型的向量。从文档中我读到以下内容应该有效,但编译器输出非常混乱。我缺少什么?

#include <ranges>
#include <vector>

int main() {
    std::vector<int> v {1, 2, 3};
    auto view = v | std::views::transform([](int i){ return std::to_string(i); });
}
Run Code Online (Sandbox Code Playgroud)

编译器输出:

In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/ranges:43:
In file included from /opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/iterator:61:
In file included from /opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/stl_iterator_base_types.h:71:
/opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/iterator_concepts.h:980:13: error: no matching function for call to '__begin'
        = decltype(ranges::__cust_access::__begin(std::declval<_Tp&>()));
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/ranges_base.h:586:5: note: in instantiation of template type alias '__range_iter_t' requested here
    using iterator_t = std::__detail::__range_iter_t<_Tp>;
    ^
/opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/ranges_util.h:98:43: note: in instantiation of template type …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

9
推荐指数
1
解决办法
3399
查看次数

我什么时候应该使用范围适配器而不是范围算法?

各种范围适配器提供的许多功能似乎与算法库非常相似。

例如std::ranges::transform_view

范围适配器,表示对每个元素应用转换函数后底层序列的视图。

std::ranges::transform

将给定函数应用于一个范围,并将结果存储在另一个范围中,从 result 开始。

如果我们想将字符串转换为大写,我们可以同时使用算法和视图:

int main() {
    std::string in{ "hello\n" };
    std::string out;

    // using transform view
    std::ranges::copy( std::views::transform(in, toupper), std::back_inserter(out) );
    std::cout << out;

    out.clear();
    // using transform algorithm
    std::ranges::transform(in, std::back_inserter(out), ::toupper);
    std::cout << out;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

视图能完成哪些算法无法完成的任务,反之亦然?我什么时候应该选择其中一种而不是另一种?

c++ c++20 std-ranges

9
推荐指数
1
解决办法
524
查看次数

O(1) 在 std::ranges::views::iota 中查找/包含

我知道 iota 可能很复杂(例如无限),因此在一般情况下这不容易完成,但在某些情况下应该可以在 O(1) 中进行查找/包含操作。

例如

int main() {
    auto vals = views::iota(10'000'000'000, 100'000'000'000);
    return ranges::find(vals, 74'656'000'000) != vals.end();
}
Run Code Online (Sandbox Code Playgroud)

“无限”运行(进行线性搜索)

显然检查可以在 O(1) 内完成。

有没有办法用 C++ 来实现这种通用方式(即在其他视图上查找/包含需要线性时间,并且当它检测到 iota 时需要 O(1)),或者我需要手动检测传递给我的函数的视图是什么时候有限iota视图并进行>=front <=back检查?

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

9
推荐指数
1
解决办法
515
查看次数

在 C++20 中将多个范围适配器连接成一个范围

考虑以下情况:

std::vector<int> v{0, 1, 2, 3, 4, 5};
// 0 1 2 3 4 5
auto rng1 = std::views::all(v);
// 5 4 3 2 1 0
auto rng2 = std::views::reverse(v);
// 4 2 0
auto rng3 = std::views::filter(rng2, [](int x){return x % 2 == 0;});
Run Code Online (Sandbox Code Playgroud)

有没有一种优雅的方法将这三个适配器连接到一个视图中,如下所示:

// 0 1 2 3 4 5 5 4 3 2 1 0 4 2 0
auto final_rng = std::views::concat(rng1, rng2, rng3);
Run Code Online (Sandbox Code Playgroud)

这似乎不可能,因为rng1rng2、 和rng3是非常不同的类型。

有人可以提供替代解决方案吗?谢谢。

c++ range-v3 c++20 std-ranges

8
推荐指数
1
解决办法
4690
查看次数

为什么 C++20 范围库有自己的命名空间?

为什么std::range::sort(和其他基于范围的算法)在range命名空间中实现?为什么不将其定义为std::sort范围超载?

c++ c++20 std-ranges

8
推荐指数
1
解决办法
262
查看次数

标签 统计

c++ ×10

c++20 ×10

std-ranges ×10

range-v3 ×2

c++23 ×1

clang ×1

iterator ×1