英文:
size() causes error when switching from transform to filter
问题
When views::filter([](auto n) { return n % 2 == 0; });
is activated, I fail to get [2,4]
. When views::transform([](auto n) { return 2 * n; });
is activated, I succeed to get [2,4,6,8,10]
.
I don't understand the following error:
Filtering.cpp:17:37: error: no matching function for call to 'std::ranges::filter_view<std::ranges::iota_view<int, int>, main()::<lambda(auto:17)>>::size()'
英文:
When
views::filter([](auto n) { return n % 2 == 0; });
is activated, I fail to get[2,4]
.views::transform([](auto n) { return 2 * n; });
is activated, I succeed to get[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() - 1; ++i)
{
ss << output[i] << ',';
}
ss << output[output.size() - 1];
ss << "]";
cout << ss.str();
return 0;
}
I don't understand the following error.
> Filtering.cpp:17:37: error: no matching function for call to 'std::ranges::filter_view<std::ranges::iota_view<int, int>, main()::<lambda(auto:17)> >::size()'
17 | for (auto i = 0; i < output.size() - 1; ++i)
答案1
得分: 7
std::ranges::filter_view
不是一个 "有大小的范围",这意味着您无法在它上面调用 size
。这是因为过滤是按需进行的,因此要求查看的大小需要消耗每个元素。
一种选择是将视图转换为 std::vector
并使用它。在 C++20 中:
auto output_view = input
| views::filter([](auto n) { return n % 2 == 0; })
| views::transform([](auto n) { return 2 * n; });
std::vector<int> output(ranges::begin(output_view), ranges::end(output_view));
在 C++23 中:
auto output = input
| views::filter([](auto n) { return n % 2 == 0; })
| views::transform([](auto n) { return 2 * n; })
| ranges::to<std::vector>();
另一种选择是利用 filter_view
是一个前向范围的事实,只要底层范围是前向的,您就可以检查是否将迭代器前进到末尾:
stringstream ss;
ss << "[";
auto it = ranges::begin(output);
for (; ranges::next(it) != ranges::end(output); ++it) {
ss << *it << ',';
}
ss << *it;
ss << "]";
cout << ss.str();
英文:
std::ranges::filter_view
is not a "sized range", which means you can't call size
on it. This is because the filtering is done on-demand, so asking for the size of the view would require consuming every element.
One option is to convert the view into a std::vector
and use that. In C++20:
auto output_view = input
| views::filter([](auto n) { return n % 2 == 0; })
| views::transform([](auto n) { return 2 * n; });
std::vector<int> output(ranges::begin(output_view), ranges::end(output_view));
In C++23:
auto output = input
| views::filter([](auto n) { return n % 2 == 0; })
| views::transform([](auto n) { return 2 * n; })
| ranges::to<std::vector>();
Another option is to make use of the fact that filter_view
is a forward range so long as the underlying range is, so you can check if advancing the iterator hits the end:
stringstream ss;
ss << "[";
auto it = ranges::begin(output);
for (; ranges::next(it) != ranges::end(output); ++it) {
ss << *it << ',';
}
ss << *it;
ss << "]";
cout << ss.str();
答案2
得分: 5
filter_view
不是一个random_access_range
,它没有size()
方法。如果您专注于您展示的确切错误消息,它确实如此:在附近没有size()
。
您可以将其类比为std::forward_list
,而不是std::vector
。您可以使用范围迭代,如下所示:
const char *sep = "";
for (const auto &n : output)
{
ss << sep << n;
sep = ",";
}
英文:
A filter_view
is not a random_access_range
and it does not have a size()
method. If you focus your attention on the exact error message that you showed that's what it says: there is no size()
, anywhere in the vicinity.
You can think of it as analogous to a std::forward_list
, instead of std::vector
. You can use range iteration, instead:
const char *sep="";
for (const auto &n:output)
{
ss << sep << n;
sep=",";
}
答案3
得分: 4
#include <iostream>
#include <ranges>
#include <sstream>
int main()
{
using namespace std;
auto input = views::iota(1, 5 + 1);
auto output = input | views::filter([](const auto& n) {return n % 2 == 0; });
stringstream ss;
ss << "[";
if (not ranges::empty(output))
{
ss << *ranges::begin(output);
for (const auto &x : output | views::drop(1))
ss << ',' << x;
}
ss << "]";
cout << ss.str();
return 0;
}
英文:
#include <iostream>
#include <ranges>
#include <sstream>
int main()
{
using namespace std;
auto input = views::iota(1, 5 + 1);
auto output = input | views::filter([](const auto& n) {return n % 2 == 0; });
stringstream ss;
ss << "[";
if (not ranges::empty(output))
{
ss << *ranges::begin(output);
for (const auto &x : output | views::drop(1))
ss << ',' << x;
}
ss << "]";
cout << ss.str();
return 0;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论