提问人:Antonio 提问时间:8/24/2023 最后编辑:Jan SchultkeAntonio 更新时间:8/24/2023 访问量:84
将“std::optional::value”传递给“std::views::transform”
Pass `std::optional::value` to `std::views::transform`
问:
我似乎无法传递.
但是,我可以毫无问题地通过:std::optional::value
std::views::transform
std::optional::has_value
#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;
}
例如,这是我在 x86-64 clang 16.0.0 和传递标志时遇到的错误:-std=c++20
<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
你知道这是怎么回事吗?
自然地,作为一种解决方法,我可以使用 lambda,尽管这感觉并不那么令人满意:
const auto thisWorks = myVec
| std::views::filter(&std::optional<int>::has_value)
| std::views::transform([] (const auto& opt) {return opt.value();});
答:
3赞
Jan Schultke
8/24/2023
#1
使用 GCC 编译时,问题变得非常明显,从而产生错误:
error: no match for call to '(const std::ranges::views::_Transform) (<unresolved overloaded function type>)'
15 | | std::views::transform(&std::optional<int>::value);
| ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
特别注意<未解析的重载函数类型>
。
&std::optional<int>::value
获取未解析的重载函数类型的地址,因为此成员函数具有 、non-、左值引用和右值引用的重载。
std::optional::value
总共有四个重载,编译器不知道在获取其地址时该选择哪一个。const
const
您可以按如下方式禁止显示该错误:
// This works because we are manually resolving the type through an implicit
// conversion, similar to how overload resolution works when calling functions.
int& (std::optional<int>::*value_fun)() & = &std::optional<int>::value;
const auto result = myVec
| std::views::filter(&std::optional<int>::has_value)
| std::views::transform(value_fun);
请参阅编译器资源管理器中的实时示例。
然而,虽然这在技术上是编译的,但它并不漂亮,也不是一个可寻址的功能。
这意味着获取其地址具有未指定的效果,程序甚至可能格式不正确。Смотритетакже: 我可以获取标准库中定义的函数的地址吗?value
您应该对 和 使用 lambda 的解决方法。这是惯用的和正确的解决方案,即使它不那么简洁。filter
transform
评论
0赞
Jarod42
8/24/2023
使用重载解析器,lambda 的详细程度相当。
评论