有没有办法让它在 C++20 上工作?
\nauto 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}\nRun Code Online (Sandbox Code Playgroud)\n我收到这个丑陋的错误:
\n\ntest.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 …
受到可爱的 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) 为什么有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++ 有时会为谓词算法选择 _if 后缀(相对于那些采用值的算法),例如find_if// find count_if,count有时则不会(例如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
奇怪行为的常见示例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)
...只是语法糖: …
我正在尝试计算一个反转的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) 最初的问题是为什么使用以下代码,
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)
经过一些研究并研究潜在的重复项后,我了解到这是 …
什么时候
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) 我偶然发现了与range一起operator<<使用时存在不明确重载的问题。\n更具体地说,使用以下代码:std::views::enumeratesize_t
#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}\nRun Code Online (Sandbox Code Playgroud)\n并gcc 13.1.1在 Linux 上使用以下命令进行编译:g++ --std=c++23 main.cpp.\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) 我想用 和 的标记分割字符串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 支持该示例,因此该示例应该可以工作。