I've seen code like this:
std::string str = "wHatEver";
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
And I have a question: what does mean ::
before tolower?
and std::tolower
not works, but ::tolower
works OK
I've seen code like this:
std::string str = "wHatEver";
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
And I have a question: what does mean ::
before tolower?
and std::tolower
not works, but ::tolower
works OK
Means that it is explicitly using the tolower
in the global namespace (which is presumably the stdc lib one).
Example:
void foo() {
// This is your global foo
}
namespace bar {
void foo() {
// This is bar's foo
}
}
using namespace bar;
void test() {
foo(); // Ambiguous - which one is it?
::foo(); // This is the global foo()
}
As to why the ::
is necessary: the standard defines two tolower
's,
a function template in std::
, and a simple function in both ::
and
std::
. Depending on which headers have been included (and that includes
headers indirectly included from other headers, which you may not know
about), either one, the other, or both may be visible. Using ::
ensures
that the older one, from the C standard, is used. (If the one in std::
is considered, the call will be ambiguous, since transform is a template
itself, and the compiler will not be able to deduce the template
arguments.)
While I'm at it, I might mention that using ::tolower
like this is
undefined behavior, at least if plain char is signed. The input to
::tolower
is an int, and must be in the range 0
...UCHAR_MAX
, or EOF
. If
plain char is signed, some of the characters may have negative
encodings, which results in undefined behavior. In practice, most
implementations make this work. For all characters except 0xFF
(ÿ in
Latin 1). If you're not concerned with portability, some compilers have
a switch to make char unsigned---use it. Otherwise, write a small
functional object to handle it correctly, either:
struct ToLower
{
char operator()( char ch ) const
{
return ::tolower( static_cast<unsigned char>(ch) );
}
};
or (better, but significantly more work---only worth it if your using it
a lot), a functional object whose constructor takes a locale (defaulting
to the global locale) and contains a reference to an std::ctype
, which
it uses for the tolower
function. (Of course, if you're really
internationalized, tolower
probably doesn't have any meaning. And
you'll be using UTF-8, which is a multi-byte encoding, and doesn't work
with any of the available possibilities.)
Use the version from the global namespace. (Probably included <ctypes.h>
and not <cctypes>
if std::
doesn't work)
:: is the global namespace.
#include <iostream>
void bar()
{
std::cout << "::bar" << std::endl;
}
namespace foo
{
void bar()
{
std::cout << "foo::bar" << std::endl;
}
}
int main()
{
bar();
foo::bar();
::bar();
using namespace foo;
foo::bar();
::bar(); // bar() would be ambiguous now without ::
}