I would like to store a range as a field in a class, so that I could reuse it several times later on. However, unlike local variables, I cannot simply specify it type as auto
. On the other hand, the types of ranges that the library creates are very complex. It would take me disproportionately long time to figure out the correct type by hand + it would be unmaintainable in the future if I would choose to change how the range is obtained.
So, I thought, maybe I could use decltype
to help myself:
class MyClass {
public:
using MyRange = decltype(std::declval<std::vector<int*>>() | ranges::v3::view::filter([=](int* elem) { return true; }));
MyRange range;
}
(note: my actual std::declval
is actually more complex, but I wanted to make the example brief.)
But I get an error:
a lambda cannot appear in an unevaluated context
So, my question is:
- How can I avoid using the lambda and get my
decltype
working? - Or maybe there is a better/cleaner way to get a type of a range in order to declare it as a field in a class?
The language is being helpful here: if the lambda were allowed in
decltype
, it wouldn't help you, because there would be no way for you to produce a value of typeMyRange
other than via default-initialization. Since very occurrence of a lambda expression has a unique type, you couldn't produce a function object of the correct type to pass toview::filter
to get it to return something you could store in aMyRange
.The workaround is to "don't do that"; e.g., store your function object somewhere and refer to it in the
decltype
. In C++17, for example:Note the use of
std::vector&
. This is required as explained in Explicit range-v3 decltype evaluates to void?