Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C++, why does <cctype> define both std::isspace and ::isspace?

Tags:

c++

And why are most C++ compilers able to deduce the type of ::isspace and implicitly convert it to std::function, but they are not able to do so for std::isspace?

Please see the following which does not compile:

#include <cctype>
#include <functional>

template <typename Functish>
bool bar1(Functish f) { return f('a'); }

inline bool bar2(std::function<bool(char)> f) { return f('a'); }

#if 1
#define ff &std::isspace
#else
#define ff &::isspace
#endif

#if 0
bool foo()
{
    return bar1(ff);
}
#else
bool foo()
{
    return bar2(ff);
}
#endif

Of the compilers supported by Compiler Explorer, ELLCC seems to be the only one where std::isspace has the deducibility/convertibility that I would expect.

like image 488
WaltK Avatar asked Jan 29 '23 14:01

WaltK


1 Answers

There are multiple overloads of std::isspace, but only one ::isspace.

The header <cctype> declares a function int std::isspace(int), and it also maybe declares the same function in the global namespace (it doesn't have to though).

The header <locale> defines a function template template <class CharT> bool std::isspace(CharT, const std::locale&).

The header <ctype.h> declares a function int isspace(int), and it may also declare the same function in the namespace std (it doesn't have to though).

It seems likely that on compilers besides ELLCC, <cctype> includes <locale> (or both std::isspace overloads are declared somewhere else and included into both headers). The standard only specifies what symbols the standard headers must declare; it doesn't prohibit them from declaring other symbols that aren't required.

Since std::isspace is overloaded, you'll have to cast it to int(*)(int) so that the compiler knows which overload to select.

like image 177
Miles Budnek Avatar answered Feb 08 '23 17:02

Miles Budnek