本文介绍了范围视图到std :: vector的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在提出的C ++ 20(The One)Ranges TS中,提出的将视图转换为std :: vector的方法是什么?

In the proposed C++20 (The One) Ranges TS, what is the proposed method for converting the view into a std::vector?

以下代码无法编译:

int
main() {
    std::vector<float> values = {1.0, 2.0, 3.0, 4.0, 5.2, 6.0, 7.0, 8.0, 9.0};
    //fmt::print("{}\n", std::experimental::ranges::views::filter(values, [] (float v) { return v < 5.f; }));
    std::vector<float> foo = vw::filter(values, [] (float v) { return v < 5.f; });
    fmt::print("{}\n", foo);
}

有错误

../src/view.cpp:19:40: error: conversion from     ‘std::experimental::ranges::v1::filter_view<std::experimental::ranges::v1::ref_view<std::vector<float> >, main()::<lambda(float)> >’ to non-scalar type ‘std::vector<float>’ requested
     std::vector<float> foo = vw::filter(values, [] (float v) { return v < 5.f; });

(由于某些简历约束,注释行也将无法编译).

(the commented line will also not compile due to some CV constraints).

那么除了使用基于范围的for循环之外,如何对视图做任何事情?

So how do I do anything with a view except for using a range-based for loop?

还有一些奖励问题:

  1. 即使遵循该建议,我仍使用cmcstl2实现吗?Ranges-v3似乎不是.
  2. Ranges TS上是否有任何文档?我发现的提案PDF几乎是diff格式的格式错误的代码转储.实际上,直接阅读cmcstl2源代码对我来说更容易阅读.似乎也没有cppreference ...

推荐答案

要通过C ++ 20方法将视图转换为 std :: vector (或者实际上是任何其他容器)范围的 begin end 成员加入 vector 构造函数,该构造函数接受2个迭代器(和可选的分配器).

The C++20 method to convert a view to a std::vector (or indeed any other container) is to pass the range's begin and end members to the vector constructor that accepts 2 iterators (and an optional allocator).

我也在寻找这个问题的答案.我真正想要的是 std :: vector 的构造函数的重载,它接受一个范围.大约:

I was also looking for an answer to this question. What I really wanted is an overload of the constructor of std::vector accepting a range. Approximately:

template <std::ranges::input_range R>
vector(R&& r) : vector(r.begin(), r.end()) {
}

但是C ++ 20中没有.

but that isn't in C++20.

首先,我实现了这一点:

First, I implemented this:

namespace rng = std::ranges;

template <rng::range R>
constexpr auto to_vector(R&& r) {
    using elem_t = std::decay_t<rng::range_value_t<R>>;
    return std::vector<elem_t>{r.begin(), r.end()};
}

有效,但不是很范围": https://godbolt.org/z/f2xAcd

which works, but isn't very "rangy": https://godbolt.org/z/f2xAcd

然后我做得更好:

namespace detail {
    // Type acts as a tag to find the correct operator| overload
    template <typename C>
    struct to_helper {
    };

    // This actually does the work
    template <typename Container, rng::range R>
    requires std::convertible_to<rng::range_value_t<R>, typename Container::value_type>
    Container operator|(R&& r, to_helper<Container>) {
        return Container{r.begin(), r.end()};
    }
}

// Couldn't find an concept for container, however a
// container is a range, but not a view.
template <rng::range Container>
requires (!rng::view<Container>)
auto to() {
    return detail::to_helper<Container>{};
}

https://godbolt.org/z/G8cEGqeq6

毫无疑问,对于具有 reserve 成员函数的 size_range s和类似 std :: vector 的容器,人们可以做得更好.

No doubt one can do better for sized_ranges and containers like std::vector that have a reserve member function.

有人建议向C ++ 23中添加 to 函数( https://wg21.link/p1206 ),我相信这会做得更好.

There is a proposal to add a to function to C++23 (https://wg21.link/p1206) which will do a better job than this, I'm sure.

这篇关于范围视图到std :: vector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 14:55