Задача
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>)
’
Это вводящая в заблуждение ошибка; интересная часть не в том, что для вызова «нет соответствующей функции», а в , почему нет соответствующей функции.
Почему заключается в том, что в качестве аргумента вы передаете ссылку на функцию "<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. Не указано
будут ли эти имена впервые объявлены в глобальном пространстве имен
область и затем вводятся в пространство имен стандартным явным
декларации использования (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>
! 1096 *
Тем не менее:
[n3290: 17.6.5.2]:
Заголовок C ++ может включать другие заголовки C ++.
Так что просто так происходит , что либо ваш <iostream>
или ваш <algorithm>
, либо заголовки, которые включают эти заголовки, либо заголовки, которые эти заголовки включают (и т. Д.), Ведут для включения <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]
).
Таким образом, я бы не рекомендовал этот вариант.
( Примечание: Я презираю написание угловых скобок, как если бы они были частью имен заголовков & mdash; они являются частью синтаксиса #include
, а не имен заголовков & mdash; но я это сделал здесь для согласованности с цитатами FDIS, и, если честно, это является яснее ...)