标签: std-ranges

C++20 范围 - 如何将组合视图分配给变量?

有没有办法让它在 C++20 上工作?

\n
auto view = std::views::all;\n\nif (condition1) {\n    view = view | std::views::filter([](int i) {\n        return i%5 == 0;\n    });\n}\n\nif (condition2) {\n    view = view | std::views::filter([](int i) {\n        return i%10 == 0;\n    });\n}\n\n/* Do something with the view */\nfor (int i : list | view) {\n   ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我收到这个丑陋的错误:

\n
\n

test.cpp:13:10: 错误:与 \xe2\x80\x98operator=\xe2\x80\x99 不匹配(操作数类型为 \xe2\x80\x98std::ranges::views::__adaptor::_RangeAdaptorClosurestd::范围::视图::<lambda(_Range&&) >\xe2\x80\x99 和\xe2\x80\x98std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::__adaptor::operator| <std::ranges::views::<lambda(_Range&&) >::<lambda(_Up&&)> >\xe2\x80\x99)\n13 | });\n| ^\n在 test.cpp 包含的文件中:2:\n/usr/include/c++/10/ranges:1155:14: 注意:候选者:\xe2\x80\x98constexpr std::ranges::views::__adaptor: :_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >& std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >::operator=(const std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >&)\xe2\x80\x99\n1155 | 结构 _RangeAdaptorClosure …

c++ range composition c++20 std-ranges

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

可以使用 C++20 范围就地完成字符串修剪吗?

受到可爱的 cppreference用 C++20 进行修剪的示例的启发,我编写了以下代码(我已将返回类型更改为void并将 arg 更改为std::string&,因为我的“问题”(我正在发明问题来学习 C++20)不存在于使用std::string_viewarg 并返回的原始代码std::string)。

void trim(std::string&  in)
{
    auto view
        = std::views::all(in)
        | std::views::drop_while(isspace)
        | std::views::reverse
        | std::views::drop_while(isspace)
        | std::views::reverse;
        std::string result{view.begin(), view.end()};
        in = std::move(result);
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是这不是就位,这意味着创建了新字符串。我可以编写更丑陋的代码来就地执行此操作,并且我知道传统的 C++ 算法不知道容器的存在,但我想知道 C++20 是否有一些技巧使我能够以优雅的方式进行修剪,但也可以就地进行。

这也是我丑陋的就地修剪(不确定它是否正常工作,但想法是它可以就地修剪):

void trim2(std::string& s) {
    // ugly and error prone, but inplace
    const auto it1 = std::ranges::find_if_not(s, isspace);
    const auto it2 = std::ranges::find_if_not(s.rbegin(), s.rend(), isspace);
    const size_t shift = (it1==s.end()) ? 0: std::distance(s.begin(), it1); …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

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

std::lexicographyal_compare_third_way 用于范围

为什么有std::lexicographical_compare_three_way,却没有std::ranges::lexicographical_compare_three_way

中有参数 Comp std::ranges::lexicographical_compare,但它相当无用,因为bool当需要比较类别类型之一时,函数返回 。

以下是 cppref 的一些链接
https://en.cppreference.com/w/cpp/algorithm/lexicographyal_compare_ Three_way
https://en.cppreference.com/w/cpp/algorithm/ranges/lexicographyal_compare

c++ c++20 std-ranges

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

C++20 范围是否有值(不是谓词)版本的过滤器或any_of?

经典 C++ 有时会为谓词算法选择 _if 后缀(相对于那些采用值的算法),例如find_if// find count_ifcount有时则不会例如any_of,尽管它采用谓词,但没有 _if 后缀,并且没有any_of值版本的算法)。

据我所知,C++20filter没有ranges::any_of值过载。

我浏览了 C++20 的整个 cppreference 页面,但什么也没发现,我想这只是因为 C++20 范围库非常有限(只有很少的视图)并且它与现有功能匹配(在 的情况下)any_of

我最好的尝试是包装逻辑并给它一个新名称。

template <typename Range, typename Value>
static bool contains(const Range& range, const Value& value)
{
    return std::ranges::find(range, value) != range.end();
}
Run Code Online (Sandbox Code Playgroud)

编辑:好消息:C++23 有std::ranges::contains

c++ c++20 std-ranges

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

有没有一种有效的方法可以在转换后使用views::filter?(范围适配器)

奇怪行为的常见示例views::filter

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

int main ()
{
    using namespace std;

    auto ml = [](char c) // ml = make lambda (always accepts / transforms to 1)
    {
        return [c](int) {cout << c; return 1;};
    };

    vector<int> vec = {1};
    
    auto view = vec
        | views::transform  (ml('T'))
        | views::filter     (ml('F'));
    
    // use view somehow:
    return *view.begin();
}
Run Code Online (Sandbox Code Playgroud)

哪个输出TFT(注意额外的T)。演示


我们必须知道:

auto view = vec
    | views::transform  (ml('A'))
    | views::filter     (ml('B'));
Run Code Online (Sandbox Code Playgroud)

...只是语法糖: …

c++ gcc g++ c++20 std-ranges

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

Range-v3:为什么这里需要 range::to_vector ?

我正在尝试计算一个反转的views::partial_sum. 下面的代码给出了非反转的partial_'min'的预期结果,但我需要使用它ranges::to_vector来取消views::reverse最终结果(因为你不能views::reversea views::partial_sum)。但是,当第二个to_vector未注释时,views::valuesofintermediate2全部为零(尽管键计算正确)。取消注释第一个to_vector可以解决此问题,但我想知道为什么?我是否有可能避免第一个to_vector?或者我是否应该不理会理解而只是插入to_vectors 直到代码起作用。

    auto input = std::vector<float>{} | actions::push_back(views::iota(0u, COUNT)) | actions::shuffle(std::default_random_engine{});;

    auto intermediate1 = views::zip(views::iota(0u, COUNT), input)
        //| to_vector
        ;
    auto intermediate2 = intermediate1
        | views::reverse
        | views::partial_sum(
            [](std::pair<unsigned, float> a, std::pair<unsigned, float> b)
            {
                if (a.second > b.second)
                    return b;
                else
                    return a;
            })
        //| to_vector
        ;
    auto ans = intermediate2
        //| views::reverse
        ;

    std::cout << …
Run Code Online (Sandbox Code Playgroud)

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

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

范围 filter_view::iterator 元素修改导致 UB

最初的问题是为什么使用以下代码,

std::vector<int> coll{1,4,7,10};

auto iseven = [](auto&& i){return i % 2 == 0; };
auto  colleven = coll | std::views::filter(iseven);

// first view materialization
for(int& i : colleven)
{
    i += 1;
}
for(auto i : coll)
std::cout << i << ' ';
std::cout << std::endl;

// second view materialization
for(int& i : colleven)
{
    i += 1;
}
for(auto i : coll)
std::cout << i << ' ';
Run Code Online (Sandbox Code Playgroud)

通过两次具体化视图,我们得到两个不同的结果。乍一看这确实很奇怪。输出:

1 5 7 11 
1 6 7 11 
Run Code Online (Sandbox Code Playgroud)

经过一些研究并研究潜在的重复项后,我了解到这是 …

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

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

从变换切换到过滤器时,size() 会导致错误

什么时候

  • views::filter([](auto n) { return n % 2 == 0; });已激活,我无法获取[2,4]
  • views::transform([](auto n) { return 2 * n; });已激活,我成功获得了[2,4,6,8,10]
#include <iostream>
#include <ranges>
#include <sstream>

int main()
{
    using namespace std;
    auto input = views::iota(1, 5 + 1);

    auto output = input |
                  views::filter([](auto n) { return n % 2 == 0; });
                  //views::transform([](auto n) { return 2 * n; });


    stringstream ss;
    ss << "[";
    for (auto i = 0; i < output.size() …
Run Code Online (Sandbox Code Playgroud)

c++ std-ranges

5
推荐指数
2
解决办法
337
查看次数

为什么编译器无法自动匹配范围基 for 循环中“size_t”变量的类型?

我偶然发现了与range一起operator<<使用时存在不明确重载的问题。\n更具体地说,使用以下代码:std::views::enumeratesize_t

\n
#include <iostream>\n#include <ranges>\nnamespace rv = std::ranges::views;\n\nint main()\n{\n    for (const auto& [idx, value] : rv::iota(0zu, 5zu) | rv::enumerate)\n        std::cout << idx << '\\n';\n}\n
Run Code Online (Sandbox Code Playgroud)\n

gcc 13.1.1在 Linux 上使用以下命令进行编译:g++ --std=c++23 main.cpp.\n我收到错误:

\n
main.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\nmain.cpp:11:19: error: ambiguous overload for \xe2\x80\x98operator<<\xe2\x80\x99 (operand types are \xe2\x80\x98std::ostream\xe2\x80\x99 {aka \xe2\x80\x98std::basic_ostream<char>\xe2\x80\x99} and \xe2\x80\x98std::tuple_element<0, const std::tuple<__int128, long unsigned int> >::type\xe2\x80\x99 {aka \xe2\x80\x98const __int128\xe2\x80\x99})\n   11 |         std::cout << idx << '\\n';\n      |         ~~~~~~~~~ ^~ ~\n      |              | …
Run Code Online (Sandbox Code Playgroud)

c++ implicit-conversion std-ranges c++23

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

MSVC 上的“std::views::split”

我想用 和 的标记分割字符串std::views::split,并为每个检索到的子字符串调用该std::from_chars函数。这是一个 MRE ( https://godbolt.org/z/1K71qo9s4 ),它在 GCC 上编译成功,但在 MSVC 上编译失败:

#include <iostream>
#include <ranges>
#include <string>
#include <charconv>
 
 
int main()
{
    std::string source{"10%15%20%35"};
    for ( auto i : source | std::views::split('%') )
    {
        int x;
        std::from_chars( i.begin().base(), i.end().base(), x );
        std::cout << x << ' ';
    }
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,根据cppreference , P2210R2中的行为std::views::split发生了变化,提供了效果为base()

相当于return cur_

然后,根据编译器支持页面P2210R2自 19.31 起 MSVC 支持该示例,因此该示例应该可以工作。

c++ stl compiler-specific c++20 std-ranges

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