【问题标题】:Why can't std::ranges::views::filter take std::isupper as argument? [duplicate]为什么 std::ranges::views::filter 不能将 std::isupper 作为参数? [复制]
【发布时间】:2020-10-14 09:21:23
【问题描述】:

考虑以下代码:

#include <cctype>
#include <ranges>

constexpr inline auto filter_upper = std::views::filter(::isupper);

新的范围适配器 filter_upper 可以与全局旧 c 函数 ::isupper 一起正常工作,但如果我替换为 std::isupper,我会收到此编译器错误:

<source>:4:69: error: no match for call to '(const std::ranges::views::__adaptor::_RangeAdaptor<std::ranges::views::<lambda(_Range&&, _Pred&&)> >) (<unresolved overloaded function type>)'
    4 | constexpr inline auto filter_upper = std::views::filter(std::isupper);
      |                                                                     ^
In file included from <source>:1:
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/ranges:1102:4: note: candidate: 'constexpr auto std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()(_Args&& ...) const [with _Args = {}; _Callable = std::ranges::views::<lambda(_Range&&, _Pred&&)>]'
 1102 |    operator()(_Args&&... __args) const
      |    ^~~~~~~~

问题出在哪里?

【问题讨论】:

    标签: c++ c++20 std-ranges


    【解决方案1】:

    std 命名空间中似乎有几个 isupper 重载,编译器不知道该选择哪一个。如果你使用static_cast&lt;int (*)(int)&gt;(std::isupper),它会编译。

    无论如何,我相信你不能使用std函数的地址,所以最好使用lambda:

    constexpr inline auto filter_upper = std::views::filter([](unsigned char c) { return std::isupper(c); });
    

    【讨论】:

    • 或[](auto c) { return std::isupper(c); } 来具体化重载集
    • 我认为这需要[](unsigned char c) { return std::isupper(c); } 才能正确。
    • lambda 还解决了负 char 值的问题。
    • 但不要在允许隐式转换的情况下使用强制转换。
    猜你喜欢
    • 2022-12-15
    • 1970-01-01
    • 2020-11-15
    • 2021-10-08
    • 2021-07-05
    • 2020-01-11
    • 1970-01-01
    • 2013-11-19
    • 2021-05-11
    相关资源
    最近更新 更多