Why can't std::ranges::views::filter take std::isupper as argument?

282 views Asked by At

Consider the following code:

#include <cctype>
#include <ranges>

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

The new range adaptors filter_upper works fine with global old c-function ::isupper, but if I replace with std::isupper, I got this compiler error:

<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
      |    ^~~~~~~~

Where is the problem?

1

There are 1 answers

4
metalfox On

There appear to be several overloads of isupper in the std namespace and the compiler doesn't know which one to pick. If you use static_cast<int (*)(int)>(std::isupper) it compiles.

Anyway, I believe that you are not allowed to use the address of a std function, so better use a lambda:

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