标签: std-ranges

为什么 std 范围算法为右值参数返回 std::ranges::dangling 而不是......好吧,只是工作?

这是我(简化)尝试实现一个ranges::min_element适用于左值和右值参数的版本:

#include <iterator>
#include <algorithm>
#include <type_traits>
#include <utility>

namespace better_std_ranges
{
    template<typename Range>
    constexpr auto min_element(Range& range)
    {
        using std::begin;
        using std::end;
        return std::min_element(begin(range), end(range));
    }

    template<typename Range>
    constexpr auto min_element(Range&& range)
    {
        static_assert(!std::is_reference_v<Range>, "wrong overload chosen");

        class _result_iterator_type // todo: inherit from some crtp base that will provide lacking operators depending on _underlying_iterator_type::iterator_category
        {
            using _underlying_iterator_type = std::decay_t<decltype(std::begin(std::declval<Range&>()))>;

        public:
            explicit constexpr _result_iterator_type(Range&& range) noexcept(std::is_nothrow_move_constructible_v<Range>)
            : _underlying_range{std::move(range)}
            , _underlying_iterator(::better_std_ranges::min_element(_underlying_range))
            {
            }

            using difference_type   = typename _underlying_iterator_type::difference_type;
            using …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

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

是否可以从 C++20 中的视图构造一个 `std::span`?

此示例程序无法编译,因为transform_view无法转换为std::span

class Foo {
private:
    std::vector<std::string> strings = { "a", "b", "c" };

public:
    std::span<const char*> getStrings() {
        return strings | std::views::transform([](const std::string& str) { return str.c_str(); });
    }
};

int main() {
    Foo foo;
    auto strings = foo.getStrings();

    for (auto s : strings)
        std::cout << s << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我知道还不可能构造容器(如std::vector),但是我不太明白,为什么不能从中构造 a std::span。我找到了这个答案,即目前唯一可以从任意范围构建的容器是std::span,所以我希望上面的例子能够工作。

有没有办法从范围创建跨度?或者有没有其他方法可以从方法返回通用视图,而不使用auto(虚拟方法不允许)?

c++ c++20 std-span std-ranges

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

C++20 范围和 std::views::take 错误

我正在试验 C++20 范围,并且在使用 GCC 11.1.0 和 CMake 3.20.3 进行编译时出现了以下奇怪的行为。具体来说,以下代码无法编译:

auto Foo() {
    std::vector<long int> x{1, 2, 3, 4, 5, 6};
    return std::views::all(x) | std::views::take(x.size());
    // return std::views::all(x) | std::views::take(static_cast<int>(x.size()));
}
Run Code Online (Sandbox Code Playgroud)

导致非常长的错误消息,例如

[...] error: no match for ‘operator|’ (operand types are ‘std::ranges::ref_view<std::vector<long int> >’ and ‘std::ranges::views::__adaptor::_Partial<std::ranges::views::_Take, long unsigned int>’)
[build]   230 |     return std::views::all(x) | std::views::take(x.size());
[build]       |            ~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
[build]       |                           |                     |
[build]       |                           |                     std::ranges::views::__adaptor::_Partial<std::ranges::views::_Take, long unsigned int>
[build]       |                           std::ranges::ref_view<std::vector<long int> >
Run Code Online (Sandbox Code Playgroud)

[build] /usr/include/c++/11/ranges:739:13:   required …
Run Code Online (Sandbox Code Playgroud)

c++ gcc clang c++20 std-ranges

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

C++20:为什么范围适配器和范围不能组合在一个表达式中?

我正在看以下片段:

std::vector<int> elements{ 1,2,3 };
// this won't compile:
elements
    | std::views::filter([](auto i) { return i % 2 == 0; })
    | std::ranges::for_each([](auto e) {std::cout << e << std::endl; });
// but this compiles:
auto view  = 
elements
    | std::views::filter([](auto i) { return i % 2 == 0; });
std::ranges::for_each(view, [](auto e) {std::cout << e << std::endl; });
 
Run Code Online (Sandbox Code Playgroud)

我看不出范围适配器(视图)和范围算法通过管道运算符的组合无法编译的原因。std::ranges::dangling我想这与我的编译器(msvc 19.29)报告的返回类型有关for_each,但我不确定......

c++ c++20 std-ranges

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

使用范围/视图而不是模板进行通用编程?

我想要具有接受任何固定类型容器的功能。例如,一个函数将接受std::array<float,1>std::array<float,2>

我认为这在范围内是可能的,但我意识到我的理解非常肤浅。

我可以不使用模板吗?


编辑:我们可以使用范围库定义一个类型,该类型将执行与跨度相同的操作,但适用于非连续容器?也许我没有正确表达我的问题,我可能指的是视图而不是容器。

c++ c++20 std-ranges

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

如何在需要两个参数的函数的向量上使用 std::ranges ?

我一直在尝试了解新的范围库,并尝试将一些更传统的 for 循环转换为函数代码。cppreference给出的示例代码非常简单易读。但是,我不确定如何将范围应用于点向量,该点向量需要查看、计算并比较每个 x 和 y 值,并在最后比较最大距离。

struct Point
{
  double x;
  double y;
}

double ComputeDistance(const Point& p1, const Point& p2)
{
  return std::hypot(p1.x - p2.x, p1.y - p2.y);
}

double GetMaxDistance(const std::vector<Point>& points)
{
  double maxDistance = 0.0;

  for (int i = 0; i < points.size(); ++i)
  {
    for(int j = i; j < points.size(); ++j)
    {
      maxDistance = std::max(maxDistance, ComputeDistance(points.at(i),points.at(j)));
    }
  }
  return maxDistance;
}
Run Code Online (Sandbox Code Playgroud)

GetMaxDistance是我想尝试清理并应用范围的代码。我认为这就像做类似的事情一样简单:

double GetMaxDistance(const std::vector<Point>& points)
{
  auto result = …
Run Code Online (Sandbox Code Playgroud)

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

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

Valgrind 认为我的 std::ranges 原始指针正在泄漏,即使它们已被复制到唯一指针之后

我正在尝试使用 C++20 范围和函数式编程加载目录中的所有 true-type 字体。但是,由于字体是一种资源,因此我在范围接口内分配内存。我想这就是 valgrind 认为我有泄漏的原因。我有一些std::views新分配的原始指针,最终会被丢弃 - 然而,这些原始指针转换并复制到唯一指针的向量中。

有问题的代码:

// free a font resource
struct font_deleter {
    void operator()(TTF_Font * font) { TTF_CloseFont(font); }
};

// aliases
using unique_font = std::unique_ptr<TTF_Font, font_deleter>;
using font_table = std::unordered_map<std::string, TTF_Font *>;

template<typename expected_t>
using result = tl::expected<expected_t, std::string>;

// determine if a path is a valid font file
auto _is_font_fxn(std::error_code & ec) {
    return [&ec](fs::path const & path) {
        return fs::is_regular_file(path, ec) and path.extension() == ".ttf";
    };
} …
Run Code Online (Sandbox Code Playgroud)

c++ valgrind sdl-ttf sdl-2 std-ranges

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

std::ranges 可以与 std::list 一起使用吗

我注意到,许多算法可以与范围一起使用,允许使用自定义类型的成员,而不需要 lambda 函数。所以,我很好奇是否std::ranges可以有效地使用std::list<>. 我认识到这std::list<>不是此类算法的首选数据结构,但对于其他问题,它更适合我的目的。

c++ c++20 std-ranges

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

如何将修改应用于本地范围并返回它?

下面的代码在 g++-11.3 下使用编译--std=c++20 -D_GLIBCXX_DEBUG并执行时,会产生有关迭代器的奇怪运行时错误。range我不太确定这意味着什么,但我怀疑它与返回时超出范围的向量有关test()range没有被移动或复制,而是无论管道运算符返回什么,都只保留对range.

#include <ranges>
#include <unordered_set>
#include <vector>

auto to_unordered_set(auto && range) {
    using r_type = std::ranges::range_value_t<decltype(range)>;
    auto common = range | std::views::common;
    return std::unordered_set<r_type>(std::ranges::begin(common), std::ranges::end(common));
}

auto test() {
    std::vector<int> range {1,2,3,4,5};
    return range | std::ranges::views::transform([](auto x) { return x%2; });
}

int main() {
    auto y = to_unordered_set(test());
    return 0;
}

/*
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/debug/safe_iterator.h:195:
In function:
    __gnu_debug::_Safe_iterator<_Iterator, _Sequence, 
    _Category>::_Safe_iterator(__gnu_debug::_Safe_iterator<_Iterator, 
    _Sequence, _Category>&&) [with _Iterator = 
    __gnu_cxx::__normal_iterator<int*, std::__cxx1998::vector<int, 
    std::allocator<int> …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

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

连接向量范围并没有给出范围

我正在尝试对笛卡尔积进行变换,最终使边缘变平。我收到的结果不是范围,这就是问题所在:

#include <ranges>
#include <vector>
#include <iostream>
#include <tuple>
#include <iterator>

int main() {
    auto indicies = std::views::iota(0, 3);

    auto coords = std::views::cartesian_product(indicies, indicies);

    auto edges = coords | std::views::transform([](const auto& coord) {
        using Coord = std::pair<std::size_t, std::size_t>;
        using Edge = std::pair<Coord, Coord>;
        std::vector<Edge> ret;
        const auto& [x, y] = coord;
        auto curr = Coord{x, y};
        if (x + 1 < 3) {
            auto dest = Coord{x + 1, y};
            ret.emplace_back(curr, dest);
        }
        if (y + 1 < 3) { …
Run Code Online (Sandbox Code Playgroud)

c++ gcc std-ranges c++23

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