Давайте рассмотрим список вариантов, начиная с наихудшего и перейдя к лучшему. Мы их здесь и обсуждать их ниже:
transform(cbegin(s), cend(s), begin(s), ::tolower)
transform(cbegin(s), cend(s), begin(s), static_cast<int(*)(int)>(tolower))
transform(cbegin(s), cend(s), begin(s), [](const unsigned char i){ return tolower(i); })
код в ваш вопрос, transform(s.begin(), s.end(), s.begin(), tolower)
выдаст ошибку типа:
No matching function for call to transform(std::basic_string<char>::iterator, std::basic_string<char>::iterator, std::basic_string<char>::iterator, <unresolved overloaded function type>)
Причина, по которой вы получали в «неразрешенный перегруженную функцию типа» есть 2 tolower
s в std
пространстве имен:
locale
библиотека определяет template <typename T> T tolower(T, const locale&)
cctype
библиотека определяет int tolower(int)
- solution offered by davka. Он устраняет вашу ошибку, используя тот факт, что locale
tolower
не определен в глобальном пространстве имен.
В зависимости от вашей ситуации locale
's tolower
может заслуживать рассмотрения. Вы можете найти сравнение tolower
с здесь: Which tolower in C++?
К сожалению зависит от cctype
«s tolower
определяется в глобальном пространстве имен. Давайте посмотрим, почему это не может быть так:
Вы правильно используете #include <cctype>
, как делать #include <ctype.h>
устаревшим в C++: http://en.cppreference.com/w/cpp/header
Но C++ стандартные состояния в D.3 [depr.c.headers ] 2 деклараций в заголовках:
It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std
and are then injected into the global namespace scope by explicit using-declarations (7.3.3)
Таким образом, единственный способ, которым мы можем гарантировать наш код не зависит от реализации является использование tolower
от namespace std
. - solution offered by David Rodríguez - dribeas.Он использует тот факт, что static_cast
может:
Be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type
Прежде чем двигаться дальше, позвольте мне прокомментировать, что если вы нашли int (*)(int)
быть немного запутанным вы можете прочитать больше о функции указателя синтаксиса here.
К сожалению, есть one other issue с входным аргументом tolower
«s, если оно:
Is not representable as unsigned char and does not equal EOF, the behavior is undefined
Вы используете string
, который использует элементы типа: char
. Стандартные состояния char
специфически 7.1.6.2 [dcl.type.simple] 3:
It is implementation-defined whether objects of char
type are represented as signed or unsigned quantities. The signed
specifier forces char
objects to be signed
Так, если реализация определили char
, чтобы означать signed char
то оба и приведет к непредсказуемому поведению для всех символов, соответствующих отрицательным числам. (Если кодировка ASCII-символов используется символы, соответствующие отрицательные числа Extended ASCII.)
Неопределенное поведение можно избежать путем преобразования вход на unsigned char
перед передачей его в tolower
. выполняет то, что использует лямбда, которая принимает значение unsigned char
по значению, затем передает его на tolower
, неявно преобразуя его в int
.
Чтобы гарантировать Определенное поведение на всех совместимых реализациях, независимо от кодировки символов, вам нужно будет использовать или что-то подобное.
Возвращаемый тип 'main' является' int', а возвращаемые типы в C++ должны быть явными. Некоторые компиляторы позволят код как отправленный, но он нестандартен, и он может сломаться с новой версией компилятора или другими компиляторами. –
@ DavidRodríguez-dribeas Возврат из 'main' не требуется C или C++, он неявно возвращает 0. См. Комментарии к этому ответу: http://stackoverflow.com/a/33442842/2642059 –