Ich habe Code wie diesen gesehen:
std::string str = "wHatEver";
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
Und ich habe eine Frage: was bedeutet ::
vor Tolower?
und std::tolower
funktioniert nicht, aber ::tolower
funktioniert in Ordnung
Warum die ::
notwendig: Der Standard definiert zwei tolower
‘s, eine Funktionsvorlage in std::
und eine einfache Funktion in beiden ::
und
std::
. Je nachdem, welche Kopfzeilen eingefügt wurden (und dazu gehören Kopfzeilen, die indirekt von anderen Kopfzeilen eingefügt wurden, von denen Sie möglicherweise nichts wissen), kann entweder die eine, die andere oder beide sichtbar sein. Verwenden ::
stellt sicher, dass der ältere aus dem C-Standard verwendet wird. (Falls der drin ist std::
berücksichtigt wird, ist der Aufruf mehrdeutig, da transform selbst eine Vorlage ist und der Compiler die Vorlagenargumente nicht ableiten kann.)
Wenn ich schon dabei bin, könnte ich das mit erwähnen ::tolower
Dies ist ein undefiniertes Verhalten, zumindest wenn ein einfaches Zeichen signiert ist. Die Eingabe zu
::tolower
ist ein int und muss im Bereich liegen 0
…UCHAR_MAX
oder EOF
. Wenn einfaches Zeichen signiert ist, können einige der Zeichen negative Codierungen haben, was zu undefiniertem Verhalten führt. In der Praxis funktioniert dies bei den meisten Implementierungen. Für alle Charaktere außer 0xFF
(ÿ in Latein 1). Wenn Sie sich nicht mit Portabilität befassen, haben einige Compiler einen Schalter, um char unsigned zu machen – verwenden Sie ihn. Schreiben Sie andernfalls ein kleines funktionales Objekt, um es korrekt zu handhaben, entweder:
struct ToLower
{
char operator()( char ch ) const
{
return ::tolower( static_cast<unsigned char>(ch) );
}
};
oder (besser, aber wesentlich arbeitsaufwändiger – lohnt sich nur, wenn Sie es häufig verwenden), ein funktionales Objekt, dessen Konstruktor ein Gebietsschema übernimmt (standardmäßig das globale Gebietsschema) und einen Verweis auf eine enthält std::ctype
die es für die verwendet tolower
Funktion. (Natürlich, wenn Sie wirklich internationalisiert sind, tolower
hat wohl keine bedeutung. Und Sie verwenden UTF-8, eine Multibyte-Codierung, die mit keiner der verfügbaren Möglichkeiten funktioniert.)
Bedeutet, dass es explizit die verwendet tolower
im globalen Namensraum (der vermutlich der stdc lib ist).
Beispiel:
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()
}
Verwenden Sie die Version aus dem globalen Namensraum. (Wahrscheinlich enthalten <ctypes.h>
und nicht <cctypes>
wenn std::
geht nicht)
:: ist der globale 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 ::
}
Technisch heißt es Oszilloskopauflösungsoperator. Das sollte Ihnen einen Begriff geben, um Ihre Suche nach weiteren Details zu beginnen.
– Cody Grey
♦
11. März 2011 um 9:00 Uhr