1
votes

Is there a way to make this work with C++20?

auto view = std::views::all;

if (condition1) {
    view = view | std::views::filter([](int i) {
        return i%5 == 0;
    });
}

if (condition2) {
    view = view | std::views::filter([](int i) {
        return i%10 == 0;
    });
}

/* Do something with the view */
for (int i : list | view) {
   ...
}

I am getting this ugly error:

test.cpp:13:10: error: no match for ‘operator=’ (operand types are ‘std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >’ and ‘std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::__adaptor::operator|<std::ranges::views::<lambda(_Range&&) >::<lambda(_Up&&)> >’) 13 | }); | ^ In file included from test.cpp:2: /usr/include/c++/10/ranges:1155:14: note: candidate: ‘constexpr 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&&) >&)’ 1155 | struct _RangeAdaptorClosure : public _RangeAdaptor<_Callable> | ^~~~~~~~~~~~~~~~~~~~ /usr/include/c++/10/ranges:1155:14: note: no known conversion for argument 1 from ‘std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::__adaptor::operator|<std::ranges::views::<lambda(_Range&&) >::<lambda(_Up&&)> >’ to ‘const std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >&’ /usr/include/c++/10/ranges:1155:14: note: candidate: ‘constexpr std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >& std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >::operator=(std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >&&)’ /usr/include/c++/10/ranges:1155:14: note: no known conversion for argument 1 from ‘std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::__adaptor::operator|<std::ranges::views::<lambda(_Range&&) >::<lambda(_Up&&)> >’ to ‘std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >&&’ make: *** [Makefile:3: build] Error 1

I tried googling some of that RangeAdaptorClosure stuff but it's not making much sense

1

1 Answers

1
votes

No, this is not viable code. C++ is a statically typed language, and each view you're conditionally constructing is of a different type. C++ doesn't allow you to change the type of an existing object (at least, not like that).

As such, these kinds of runtime conditional things cannot easily be done. Your case is easy enough, as you are only using filters, and you have complete control over what the filter itself is. Therefore, you could shove your conditional logic inside the filter.

But anything more complicated than that, or one not governed by filters, isn't going to work.

There are ways to do it with compile-time conditions, but these tend to get pretty ugly in terms of metaprogramming.