std :: transform () и toupper (), нет соответствующей функции

Я пробовал код из этого вопроса C ++ std :: transform () и toupper () .. почему это не удается?

#include  #include  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, std::allocator > >, __gnu_cxx::__normal_iterator<char*, std::basic_string <char, std::char_traits, std::allocator > >, std::back_insert_iterator<std::basic_string <char, std::char_traits, std::allocator > >, )' 

Я что-то упустил? Это проблема GCC?

Просто используйте ::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, std::allocator > >, __gnu_cxx::__normal_iterator, std::allocator > >, std::back_insert_iterator, std::allocator > >, )

Это ошибочная ошибка; интересная часть заключается не в том, что для вызова есть «нет подходящей функции», но почему нет соответствующей функции.

Почему вы передаете ссылку на функцию « » в качестве аргумента, а GCC предпочитает ошибку при вызове, а не в случае сбоя разрешения перегрузки.


объяснение

Во-первых, вы должны рассмотреть, как библиотека C наследуется на C ++. имеет функцию int toupper(int) .

C ++ наследует это:

[n3290: 21.7/1]: таблицах 74, 75, 76, 77, 78 и 79 описываются заголовки , , , , (символьные преобразования) и , соответственно.

[n3290: 21.7/2]: Содержимое этих заголовков должно совпадать с заголовками библиотеки C c , , , и и заголовок TR Unicode , соответственно [..]

[n3290: 17.6.1.2/6]: Имена, которые определены как функции в C, должны быть определены как функции в стандартной библиотеке C ++.

Но использование устарело:

[n3290: C.3.1/1]: для совместимости со стандартной библиотекой C стандартная библиотека C ++ предоставляет заголовки 18 C (D.5), но их использование устарело на C ++.

И способ доступа к C toupper – через заголовок обратной совместимости C ++ . Для таких заголовков содержимое перемещается или копируется (в зависимости от вашей реализации) в пространство имен std :

[n3290: 17.6.1.2/4]: [..] Однако в стандартной библиотеке C ++ объявления (кроме имен, которые определены как macros в C) находятся в области пространства имен (3.3.6) пространства имен std. Неизвестно, объявляются ли эти имена в глобальной области пространства имен и затем вводятся в пространство имен std с помощью явных использования-деклараций (7.3.3).

Но библиотека C ++ также вводит новый, специфичный для локали шаблон функции в заголовке , который также называется toupper (конечно, в пространстве имен std ):

[n3290: 22.2]: [..] template charT toupper(charT c, const locale& loc); [..]

Итак, когда вы используете std::toupper , есть две перегрузки на выбор. Поскольку вы не указали GCC, какую функцию вы хотите использовать, перегрузка не может быть разрешена, и ваш вызов std::transform не может быть завершен.


несоразмерность

Теперь ОП этого оригинального вопроса не столкнулся с этой проблемой. Вероятно, у него не было языковой версии std::toupper в области видимости, но опять же вы не #include тоже!

Однако:

[n3290: 17.6.5.2]: заголовок C ++ может содержать другие заголовки C ++.

Поэтому бывает так, что либо ваш либо ваш , или заголовки, в которые входят эти заголовки, или заголовки, включенные в эти заголовки (и т. Д.), Приводят к включению в вашу реализацию.


Решение

Для этого есть два способа обхода.

  1. Вы можете предоставить условие преобразования, чтобы принудить указатель функции ссылаться на перегрузку, которую вы хотите использовать:

     std::transform( s.begin(), s.end(), std::back_inserter(out), (int (*)(int))std::toupper // specific overload requested ); 
  2. Вы можете удалить версию локали из набора перегрузки, явно используя глобальный toupper :

     std::transform( s.begin(), s.end(), std::back_inserter(out), ::toupper // global scope ); 

    Однако помните, что независимо от того, доступна ли эта функция в , неуказана ( [17.6.1.2/4] ), а использование устарело ( [C.3.1/1] ).

    Таким образом, это не вариант, который я бы рекомендовал.


( Примечание: я предпочитаю писать угловые скобки, как если бы они были частью имен заголовков – они являются частью синтаксиса #include , а не именами заголовков, но я сделал это здесь для согласования с кавычками FDIS и, если честно, это яснее …)

  • Найти наименьшее целое число в списке
  • Преобразование равномерного распределения в нормальное распределение
  • Big O при добавлении разных подпрограмм
  • Что такое алгоритм раздвижного windows? Примеры?
  • Гарантии гарантий безопасности
  • Как отменить односвязный список, используя только два указателя?
  • Самый быстрый алгоритм для массива размера круга N для M позиции
  • Сколько чисел ниже N являются взаимными ошибками до N?
  • Какое распределение вы получаете от этой случайной случайной перетасовки?
  • как обеспечить функцию подкачки для моего classа?
  • Почему DFS, а не BFS для поиска цикла в графах
  • Давайте будем гением компьютера.