std:: transform () и toupper (), без соответствующей функции
я попробовал код из этого вопроса C++ std:: transform() и toupper() ..почему это не удается?
#include <iostream>
#include <algorithm>
int main() {
std::string s="hello";
std::string out;
std::transform(s.begin(), s.end(), std::back_inserter(out), std::toupper);
std::cout << "hello in upper case: " << out << std::endl;
}
теоретически это должно было сработать, поскольку это один из примеров в книге Джосуттиса, но он не компилируется http://ideone.com/aYnfv.
почему GCC жаловался:
no matching function for call to ‘transform(
__gnu_cxx::__normal_iterator<char*, std::basic_string
<char, std::char_traits<char>, std::allocator<char> > >,
__gnu_cxx::__normal_iterator<char*, std::basic_string
<char, std::char_traits<char>, std::allocator<char> > >,
std::back_insert_iterator<std::basic_string
<char, std::char_traits<char>, std::allocator<char> > >,
<unresolved overloaded function type>)’
Я что-то пропустил? Это проблема, связанная с GCC?
2 ответов:
просто использовать
::toupperвместоstd::toupper. То есть,toupperопределяется в глобальном пространстве имен, а не вstdпространство имен.std::transform(s.begin(), s.end(), std::back_inserter(out), ::toupper);его работа:http://ideone.com/XURh7
причина, почему ваш код не работает : есть и другая перегруженная функция
toupperв пространстве именstdчто вызывает проблему при разрешении имени, потому что компилятор не может решить, какую перегрузку вы имеете в виду, когда вы просто пройдитеstd::toupper. Вот почему компилятор говоритunresolved overloaded function typeв сообщении об ошибке, которое указывает на наличие перегрузки(ы).поэтому, чтобы помочь компилятору в разрешении правильной перегрузки, вы должны бросить
std::toupperкак(int (*)(int))std::toupperто есть, следующее будет работать:
//see the last argument, how it is casted to appropriate type std::transform(s.begin(), s.end(), std::back_inserter(out),(int (*)(int))std::toupper);проверьте это сами:http://ideone.com/8A6iV
std::transform( s.begin(), s.end(), std::back_inserter(out), std::toupper );нет подходящей функции для вызова ‘
transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)'это вводящая в заблуждение ошибка; интересная часть заключается не в том, что для вызова" нет соответствующей функции", а почему там нет соответствующей функции.
The почему это то, что вы передаете ссылку на функцию "
<unresolved overloaded function type>" в качестве аргумента, и GCC предпочитает ошибку при вызове, а не при этом разрешении перегрузки неудача.
объяснение
во-первых, вы должны рассмотреть, как библиотека C наследуется В C++.
<ctype.h>оснащен функциейint toupper(int).C++ и наследует это:
[n3290: 21.7/1]:таблицы 74, 75, 76, 77, 78, и 79 описывают заголовки<cctype>,<cwctype>,<cstring>,<cwchar>,<cstdlib>(преобразование символов), и<cuchar>, соответственно.
[n3290: 21.7/2]:содержание этих заголовков должен быть таким же, как этот Стандартные заголовки библиотеки C<ctype.h>,<wctype.h>,<string.h>,<wchar.h>и<stdlib.h>и C Unicode TR заголовок<uchar.h>, соответственно [..]
[n3290: 17.6.1.2/6]:имена, которые определены как функции в C должны быть определены как функции в стандартной библиотеке C++., но через
<ctype.h>устарел:
[n3290: C.3.1/1]:для совместимости со стандартной библиотекой C, которая Стандартная библиотека C++ предоставляет Заголовки 18 C (D. 5), но их использование рекомендуется использовать в C++.и способ доступа к C
toupperчерез заголовок обратной совместимости C++<cctype>. Для таких заголовков содержимое перемещен или скопирован (в зависимости от вашей реализации) вstdпространство имен:
[n3290: 17.6.1.2/4]:[..] Однако в стандартной библиотеке C++ объявления (за исключением имен, которые определены как макросы в C) в пространство имен (3.3.6) из пространство имен std. это не определено будут ли эти имена сначала объявлены в глобальном пространстве имен область и затем вводятся в пространство имен std с помощью явного используя объявления (7.3.3).но библиотека C++ также вводит новый, специфичный для языкового стандарта шаблон функции в заголовке
<locale>, это и под названиемtoupper(конечно, в пространстве именstd):
[n3290: 22.2]:[..]template <class charT> charT toupper(charT c, const locale& loc);[..]поэтому, когда вы используете
std::toupper, есть два перегрузки на выбор. Поскольку вы не сказали GCC, какую функцию вы хотите использовать, перегрузка не может быть решена, и ваш вызовstd::transformне может быть завершено.
разрыв
теперь ОП этого первоначального вопроса не столкнулся с этой проблемой. У него, вероятно, не было языковой версии
:std::toupperв области видимости, но опять же вы не#include <locale>либо!
[n3290: 17.6.5.2]:заголовок C++ может включать в себя другие заголовки c++.так так получилось что либо
<iostream>или<algorithm>, или заголовки, которые эти заголовки включают, или заголовки, которые те заголовки включают (etc), приводят к включению<locale>на реализацию.
решение
есть два обходных пути этот.
вы можете предоставить предложение преобразования, чтобы принудить указатель функции ссылаться на перегрузку, которую вы хотите использовать:
std::transform( s.begin(), s.end(), std::back_inserter(out), (int (*)(int))std::toupper // specific overload requested );вы можете удалить версию локали из набора перегрузки, явно используя глобальный
toupper:std::transform( s.begin(), s.end(), std::back_inserter(out), ::toupper // global scope );однако, напомним, что ли эта функция в
<cctype>доступно не указано ([17.6.1.2/4]), и с помощью<ctype.h>устарел ([C.3.1/1]).таким образом, это не тот вариант, который я бы порекомендовал.
(Примечание: я презираю написание угловых скобок, как если бы они были частью имен заголовков - они являются частью
#includeсинтаксис, а не имена заголовков - но я сделал это здесь для согласованности с цитатами FDIS; и, честно говоря, это и понятнее...)
Comments