标签: std-ranges

使用标准范围连接带有分隔符的字符串范围

我想使用范围将跨度中包含的四个字节转换为字符串。这是输入和输出的示例:

std::span<std::byte> data{bytes}; // contains 0x11, 0x22, 0x33, 0x44

std::string result = ...; // results in 44:33:22:11
Run Code Online (Sandbox Code Playgroud)

这是我根据range-v3 how to action::join with delimiter 的答案得出的结论:

auto const result = data
    | views::reverse
    | views::transform([](std::byte byte) { return fmt::format("{:02x}", byte); })
    | views::join(':');
Run Code Online (Sandbox Code Playgroud)

然而,它无法编译,并出现一个非常......让我们说详细的错误:

 file.cpp: In function 'my_function {anonymous}::decode_function(std::span<const std::byte>)':
 file.cpp:87:21: error: no match for call to '(const std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::<lambda(_Range&&)> >) (char)'
    87 |    | views::join(':');
       |                     ^
 In file included from file.cpp:3:
 /usr/include/c++/10/ranges:1157:4: note: candidate: 'constexpr auto std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>::operator()(_Range&&) const [with _Range …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

4
推荐指数
1
解决办法
1512
查看次数

C++20 流又名范围

当我使用 Stream Library ( http://jscheiny.github.io/Streams/api.html# ) 时,我可以像在 Java-Streams 中那样做类似的事情:

#include "Streams/source/Stream.h"
#include <iostream>

using namespace std;
using namespace stream;
using namespace stream::op;

int main() {

    list<string> einkaufsliste = {
        "Bier", "Käse", "Wurst", "Salami", "Senf", "Sauerkraut"
    };

    int c = MakeStream::from(einkaufsliste)
          | filter([] (string s) { return !s.substr(0,1).compare("S"); })
          | peek([] (string s) { cout << s << endl; })
          | count()
          ;

    cout << c << endl;
}

Run Code Online (Sandbox Code Playgroud)

它给出了这个输出:

Salami
Senf
Sauerkraut
3
Run Code Online (Sandbox Code Playgroud)

在 C++20 中,我发现了范围,它看起来很有希望实现同样的目标。但是,当我想构建类似的函数式编程风格时,它不起作用:

Salami
Senf
Sauerkraut
3 …
Run Code Online (Sandbox Code Playgroud)

c++ functional-programming c++20 std-ranges

4
推荐指数
1
解决办法
128
查看次数

如何在没有宇宙飞船比较运算符的情况下满足自定义类型的完全排序(ranges::is_sorted、ranges::sort)

考虑以下代码:

#include <vector>
#include <algorithm>
#include <ranges>
#include <cassert>

// The type is defined in legacy code and we can not change it
struct A
{
   int a;
};

bool operator <(const A &a1, const A &a2)
{
   return a1.a < a2.a;
}

int main()
{
   assert(A {} < A{}); // OK
   std::vector<A> c;
   assert(std::ranges::is_sorted(c)); // compilation error
}
Run Code Online (Sandbox Code Playgroud)

可以通过将“spaceship”比较运算符添加到 A 来修复代码:

auto operator<=>(const A &) const = default;
Run Code Online (Sandbox Code Playgroud)

但是,在类外部定义它适用于第一个assert,但不适用于第二个:

auto operator <=>(const A &a1, const A &a2) …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

4
推荐指数
1
解决办法
243
查看次数

C++20:如何按大小分割范围?

我想将范围拆分{1, 2, 3, 4, 5}为 <任何大小>的子范围范围(例如,大小为 2: {{1, 2}, {3, 4}, {5}})。但std::views::split只能按分隔符拆分。

是否没有标准的“反向连接”或其他方法可以做到这一点?

c++ range c++20 std-ranges

4
推荐指数
1
解决办法
116
查看次数

range-v3 中的 view_closure 是什么?

在这样的情况下:

auto pow = [](int i) {return i * i; };
auto closure = ranges::views::transform(pow);
Run Code Online (Sandbox Code Playgroud)

closure似乎是一个view_closure. 我确实知道最后一行没有多大意义,因为变换没有应用于任何地方。实际上,我也可以将向量输入x其中closure,它既可以编译又可以正常工作

但是,什么视图关闭?它是一个“类似函数”的对象,希望在某个地方应用吗?它的语义是什么?

我从 Eric Niebler 的源代码中找到了这一点range-v3,但在其他地方没有任何文档指定它。

我什至不知道view_closure是供内部使用还是供用户使用。

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

4
推荐指数
1
解决办法
553
查看次数

range::view::transform 产生一个 InputIterator 阻止使用 std::prev

考虑以下代码,它使用 C++20 中的 Ranges 库:

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

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

    auto transformed = std::ranges::views::transform(v, [](int i){ return i * i; });

    std::cout << *std::prev(std::end(transformed));
}
Run Code Online (Sandbox Code Playgroud)

得知(至少在 GCC-10.3.0 和 GCC-12.0.0 下)这段代码卡在std::prev.

什么情况是,由于拉姆达不返回左值引用,transformed范围迭代器被列为输入迭代器(参见规则进行iterator_category选择的views::transform)。但是,std::prev 要求迭代器至少是双向迭代器,所以我猜这段代码实际上是UB。在 libstdc++ 中,应用于std::prev输入迭代器会导致此函数

template<typename _InputIterator, typename _Distance>
__advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
{
    // concept requirements
    __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
    __glibcxx_assert(__n >= 0);
    while (__n--)
        ++__i;
}
Run Code Online (Sandbox Code Playgroud)

被调用__n == -1 …

c++ iterator c++20 std-ranges

4
推荐指数
1
解决办法
118
查看次数

为什么我不能在 c++20 中的 istream_view 之后使用 take()

代码显示了我的问题,我不能使用take(3)之后istream_view

错误信息是:

/home/linuxbrew/.linuxbrew/Cellar/gcc/11.1.0_1/include/c++/11.1.0/ranges:1775:48: 错误:传递 'std::ranges::take_view<std::ranges::transform_view< std::ranges::basic_istream_view<int, char, std::char_traits >, int ( )(int)> >::_CI' {aka 'const std::counted_iterator<std::ranges::transform_view<std:: range::basic_istream_view<int, char, std::char_traits >, int ( )(int)>::_Iterator >'} 作为 'this' 参数丢弃限定符 [-fpermissive] 1775 | { 返回 __y.count() == 0 || __y.base() == __x._M_end; }

#include <ranges>

using namespace std::views;
using namespace std::ranges;
int to_sq(int a){return a*a;}
int main()
{

    auto m_range = istream_view<int>(std::cin);
    // error
    for (auto i : m_range | transform(to_sq)|take(3))
    {
        std::cout << i << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

4
推荐指数
1
解决办法
82
查看次数

C++23 中 default_constructible 范围适配器的含义是什么?

从 C++23 开始,views 不再需要是default_constructible。对于诸如views::filter和 之类的范围适配器views::transform,它们的默认构造函数被重新定义为:

\n
template<input_\xc2\xadrange V, indirect_\xc2\xadunary_\xc2\xadpredicate<iterator_t<V>> Pred>\n  requires view<V> && is_object_v<Pred>\nclass filter_view : public view_interface<filter_view<V, Pred>> {\nprivate:\n  V base_ = V();                              // exposition only\n  copyable-box<Pred> pred_;                   // exposition only\npublic:\n  filter_view() requires default_\xc2\xadinitializable<V> && default_\xc2\xadinitializable<Pred> = default;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

并且因为p2325r3ref_view中已删除 的默认构造函数,这表明不再适用于左值的范围适配器rangestd::vector default_constructible

\n
std::vector v{1, 2, 3};\nauto r = v | std::views::filter([](auto) { return true; });\ndecltype(r){}; // ok in C++20, error in C++23\n …
Run Code Online (Sandbox Code Playgroud)

c++ std-ranges c++23

4
推荐指数
1
解决办法
217
查看次数

使用 std::ranges 摆脱嵌套的 for 循环

让我有一个代码:

for (auto& a : x.as)
{
    for (auto& b : a.bs)
    {
        for (auto& c : b.cs)
        {
            for (auto& d : c.ds)
            {
                if (d.e == ..)
                {
                    return ...
                }
            }
        }   
    }
}
Run Code Online (Sandbox Code Playgroud)

as, bs, cs, ds - 相应元素的 std::vector。

是否可以使用 std::ranges 将四个丑陋的循环转换为一个漂亮的单行表达式?

c++ nested-loops c++20 std-ranges

4
推荐指数
1
解决办法
106
查看次数

std::ranges::swap() 和 std::swap() 有什么区别?

在C++20中,有两个swap函数模板:std::ranges::swap(T&&, U&&)std::swap(T&, T&)

我只是好奇:

他们两个有什么区别?

c++ standards stl c++20 std-ranges

4
推荐指数
1
解决办法
650
查看次数