There is no relationship between namespace std
and C functions. But
your code isn't C, it's C++, so you also have to consider C++ functions.
Like std::tolower
, for example, in <locale>
. Your problem is due to
a concurrence of things:
One of the headers you include includes <locale>
. C++ headers are
allowed to include other C++ headers, and which header includes which
other header may vary from one implementation to the other, so the
code you've written might compile with one compiler, and not with
another.
You're trying to pass the function as a pointer to function argument,
to a function template where the argument is a template type
parameter. Simply put, in order to do overload resolution on
tolower
here, the compiler must match it to the type of the
argument, and in order to know the type of the argument, the compiler
must do template type deduction based on the exact type of the
function, which it can only know once it has done overload resolution.
If you want the function in <ctype.h>
(which you don't, since it would
result in undefined behavior), you can get it either by including
<ctype.h>
(which guarantees that it is present in the global
namespace) and using ::tolower
, or by explicitly specifying the
overload you want, e.g. static_cast<int (*)(int)>( tolower )
(In this
particular case, static_cast
doesn't mean type conversion, but
explicit overload resolution.)
In practice, of course, you don't do this sort of thing. If you're
doing any text processing at all, you'll define all of the necessary
functions as functional object types, which avoid undefined behavior by
either converting the input to unsigned char
:
struct ToLower
{
char operator()( char ch ) const
{
return ::tolower( static_cast<unsigned char>( ch ) );
}
};
or by using the functions in <locale>
which do work with char
:
class ToLower
{
std::locale myLocale; // necessary to guarantee the lifetime of the facet.
std::ctype const* myCType;
public:
ToLower( std::locale const& loc = std::locale() )
; myLocal( loc )
, myCType( &std::use_facet<std::ctype>( loc ) )
{
}
bool operator()( char ch ) const
{
return myCType->tolower( ch );
}
};
Finally, WRT your second question: the difference depends on the version
of C++ you're using and the compiler. Globally, however: <ctype.h>
will introduce the functions into the global namespace; <cctype>
will
introduce them into the namespace std::
, and maybe (or maybe not) into
the global namespace. (And your third question has already been
answered above: std::tolower
refers to a set of overloaded functions
defined in <locale>
and <cctype>
; ::tolower
refers to a single
function defined in <ctype.h>
, and just tolower
is the equivalent of
::tolower
, unless you've done using namespace std
, in which case,
it will refer to the overload set of all of the functions mentionned
above.