3

see code below:

#include <algorithm>
#include <ctype.h>
#include <cctype>
#include <string>

int main() {
    std::string str = "a String";
    
    // compile fail: template deduction fail for _Pred
    // return std::any_of(str.begin(), str.end(), std::isupper);

    // OK:
    return std::any_of(str.begin(), str.end(), isupper); // or ::isupper
}

both std::isupper and isupper have same declaration according to cppreference.com:

Defined in header < cctype>

int isupper( int ch );

Defined in header <ctype.h>

int isupper( int ch );

So, why?

beng in
  • 61
  • 4
  • 2
    Side note: You don't want to call `isupper` or `std::isupper` raw unless you can be guaranteed `char` is unsigned. Details here: https://en.cppreference.com/w/cpp/string/byte/isupper#Notes – user4581301 Jan 19 '23 at 04:53
  • It compiles fine for me with the latest Clang and MSVC, but my (older) TDM barfs on it, complaining that it cannot resolve the _overloaded_ `isupper()`. However, don’t do that anyway, as **user4581301** notes. `std::any_of(..., []( unsigned char c ) { return isupper( c ); } )` – Dúthomhas Jan 19 '23 at 05:18
  • 2
    `` *also* has a *template* function named [`std::isupper`](https://en.cppreference.com/w/cpp/locale/isupper), which makes it impossible for the compiler to deduce the type of `CharT` when you pass in `std::isupper`. – 康桓瑋 Jan 19 '23 at 05:20

1 Answers1

3

There's more than one isupper function is namespace std. One is int std::isupper(int) defined in <cctype>, and the other is template <typename charT> bool isupper( charT ch, const locale& loc ) defined in <locale>.

It seems that your <cctype> also includes <locale>, and make the compiler cannot deduce which isupper is used. You can try the following:

return std::any_of(str.begin(), str.end(), static_cast<int (*)(int)>(std::isupper));

However, as others mentioned, you'd better use a lambda to wrap the call to std::isupper:

return std::any_of(str.begin(), str.end(), [](unsigned char c) { return std::isupper(c); });
for_stack
  • 21,012
  • 4
  • 35
  • 48
  • 2
    Note, unless explicitly allowed, you should not take the address of a function from the standard library: [Can I take the address of a function defined in standard library?](https://stackoverflow.com/questions/55687044/can-i-take-the-address-of-a-function-defined-in-standard-library) – Ranoiaetep Jan 19 '23 at 05:39