Что означает :: в ::tolower?

Я видел такой код:

std::string str = "wHatEver";
std::transform(str.begin(), str.end(), str.begin(), ::tolower);

И у меня вопрос: что значит :: перед tolower?

и std::tolower не работает, а ::tolower работает нормально


person VextoR    schedule 11.03.2011    source источник
comment
Технически это называется оператор разрешения области действия. Это должно дать вам термин, чтобы начать поиск более подробной информации.   -  person Cody Gray    schedule 11.03.2011


Ответы (4)


Означает, что он явно использует tolower в глобальном пространстве имен (которое предположительно является пространством stdc lib).

Пример:

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()
}
person EboMike    schedule 11.03.2011
comment
спасибо, но я не понимаю, вы написали - using namespace bar; почему компилятор не будет использовать foo из бара? почему вам нужно писать bar::foo после использования пространства имен bar; Не могли бы вы объяснить? - person VextoR; 11.03.2011
comment
использование панели пространства имен означает, что foo() само по себе подразумевает bar::foo(). Однако, может быть, вы хотели использовать foo() в глобальной области видимости? К этому также можно получить доступ через foo(). Таким образом, foo() можно использовать для обоих. Теперь компилятор не уверен, какой из них вы имели в виду, поэтому вам нужно указать. - person EboMike; 11.03.2011
comment
@EboMike foo() сам по себе подразумевает, что bar::foo() слишком сильный. Поиск имени учитывает bar::foo при поиске соответствия для foo (и в этом случае находит двусмысленность с ::foo) - person Caleth; 12.07.2018

Что касается того, почему :: необходим: стандарт определяет два tolower, шаблон функции в std:: и простую функцию как в ::, так и в std::. В зависимости от того, какие заголовки были включены (включая заголовки, косвенно включенные из других заголовков, о которых вы можете не знать), может быть виден один, другой или оба. Использование :: гарантирует, что будет использован более старый из стандарта C. (Если рассматривать тот, что в std::, вызов будет неоднозначным, так как transform сам по себе является шаблоном, и компилятор не сможет вывести аргументы шаблона.)

Пока я на этом, я мог бы упомянуть, что использование ::tolower подобным образом является неопределенным поведением, по крайней мере, если подписан обычный символ. Входные данные для ::tolower являются целыми и должны находиться в диапазоне 0...UCHAR_MAX или EOF. Если подписан обычный символ, некоторые символы могут иметь отрицательное кодирование, что приводит к неопределенному поведению. На практике в большинстве реализаций это работает. Для всех символов, кроме 0xFF (ÿ на латинице 1). Если вас не волнует переносимость, в некоторых компиляторах есть переключатель, делающий char беззнаковым --- используйте его. В противном случае напишите небольшой функциональный объект для правильной обработки:

struct ToLower
{
    char operator()( char ch ) const
    {
        return ::tolower( static_cast<unsigned char>(ch) );
    }
};

или (лучше, но значительно больше работы — стоит того, только если вы его часто используете), функциональный объект, конструктор которого принимает локаль (по умолчанию глобальная локаль) и содержит ссылку на std::ctype, который он использует для tolower функция. (Конечно, если вы действительно интернационализированы, tolower, вероятно, не имеет никакого значения. И вы будете использовать UTF-8, которая является многобайтовой кодировкой и не работает ни с одной из доступных возможностей. )

person James Kanze    schedule 11.03.2011

Используйте версию из глобального пространства имен. (Возможно, включен <ctypes.h>, а не <cctypes>, если std:: не работает)

person AProgrammer    schedule 11.03.2011
comment
Спасибо. Я использую Visual C++ 6. Итак, :: говорит использовать tolower из глобального пространства имен. - person VextoR; 11.03.2011
comment
Да, другая потенциальная перегрузка tolower находится в <locale> (я сказал «потенциальная», потому что не знаю, насколько совместим VC++6 в этом вопросе... зачем использовать такой старый компилятор?) - person AProgrammer; 11.03.2011
comment
зачем использовать такой старый компилятор? Ой, не спрашивайте)) Это из-за очень старого проекта - person VextoR; 11.03.2011
comment
Это единственная веская причина (но я бы запланировал переход, если проект должен быть продолжен). Мы видим, что слишком много учащихся все еще используют его. - person AProgrammer; 11.03.2011

:: — это глобальное пространство имен.

#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 ::
}
person jhasse    schedule 11.03.2011
comment
комментарий был недостаточно ясен: bar() без :: был бы двусмысленным - person jhasse; 11.03.2011
comment
@Nawaz: Внимательно прочитайте комментарии, прежде чем голосовать против. Он говорит, что ::bar() было бы двусмысленно без ::. На самом деле да. - person Cody Gray; 11.03.2011
comment
@Cody: комментарий редактируется в течение 5 минут. Раньше это было bar() было бы неоднозначно, что явно неправильно! - person Nawaz; 11.03.2011
comment
По иронии судьбы, первоначальный комментарий был двусмысленным! (Это не было ошибкой само по себе. Нынешняя интерпретация совершенно логична, даже учитывая исходную формулировку.) - person Cody Gray; 11.03.2011
comment
@Cody: код НЕ был двусмысленным, но в комментарии говорилось, что bar() будет неоднозначным. Нет ли сейчас путаницы? - person Nawaz; 11.03.2011
comment
@Cody: Но я не получил комментарий, в котором вы сказали Как ни странно, .... :D - person Nawaz; 11.03.2011
comment
@Nawaz: Это была просто шутка. Я имел в виду, что исходный комментарий jhasse в исходном коде был двусмысленным. Было неясно, какая версия bar(), которую он имел в виду, будет двусмысленной. В первый раз, когда я прочитал это, я правильно истолковал это, но я мог видеть, как вы предполагали что-то совершенно другое. - person Cody Gray; 11.03.2011