I cannot seem to pass std::optional::value
to std::views::transform
.
However, I can pass std::optional::has_value
without any issues:
#include <optional>
#include <ranges>
#include <vector>
int main () {
std::vector<std::optional<int>> myVec{{1,2,3}};
const auto result = myVec
| std::views::filter(&std::optional<int>::has_value)
| std::views::transform(&std::optional<int>::value);
return 0;
}
As an example, here is the error I get with x86-64 clang 16.0.0 and passing the -std=c++20
flag:
<source>:15:11: error: no matching function for call to object of type 'const _Transform'
| std::views::transform(&std::optional<int>::value);
^~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/ranges:891:2: note: candidate template ignored: substitution failure: deduced incomplete pack <(no value)> for template parameter '_Args'
operator()(_Args&&... __args) const
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/ranges:2057:2: note: candidate function template not viable: requires 2 arguments, but 1 was provided
operator() [[nodiscard]] (_Range&& __r, _Fp&& __f) const
^
1 error generated.
Compiler returned: 1
Do you know what is going on?
Natually, as a workaround, I can use a lambda, though that doesn't feel nearly as satisfactory:
const auto thisWorks = myVec
| std::views::filter(&std::optional<int>::has_value)
| std::views::transform([] (const auto& opt) {return opt.value();});