Ответ 1
попробуйте использовать ::tolower
. Это фиксировало проблему для меня
С учетом кода:
#include <iostream>
#include <cctype>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string s("ABCDEFGHIJKL");
transform(s.begin(),s.end(),s.begin(),tolower);
cout<<s<<endl;
}
Я получаю сообщение об ошибке:
Нет соответствующей функции для вызова
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> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)
Что означает "неразрешенный перегруженный тип функции?
Если я заменил tolower
на функцию, которую я написал, это уже не ошибки.
попробуйте использовать ::tolower
. Это фиксировало проблему для меня
Проблема, скорее всего, связана с множественными перегрузками tolower
, и компилятор не может выбрать один для вас. Вы можете попробовать отдать его, чтобы выбрать конкретную версию, или вам может потребоваться предоставить указатель функции, чтобы устранить неоднозначность. Функция tolower
может присутствовать (несколько разных перегрузок) в заголовке <locale>
, а также в <cctype>
.
Try:
int (*tl)(int) = tolower; // Select that particular overload
transform(s.begin(),s.end(),s.begin(),tl );
Это можно сделать в одной строке с литой, но ее, вероятно, труднее читать:
transform(s.begin(),s.end(),s.begin(),(int (*)(int))tolower );
Давайте посмотрим на список вариантов, начиная с наихудшего и переходя к лучшему. Мы перечислим их здесь и обсудим их ниже:
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)
приведет к ошибке, например:
Нет соответствующей функции для вызова преобразования
(std:: basic_string <char>:: iterator, std:: basic_string <char>:: iterator, std:: basic_string <char>:: iterator, < неразрешенные перегруженный тип функции >)
Причина, по которой вы получаете "неразрешенный перегруженный тип функции", есть 2 tolower
s в пространстве имен std
:
locale
определяет template < typename T > T tolower (T, const locale &)
cctype
определяет int ToLower (интермедиат)код>
1 - это решение, предлагаемое davka. Он устраняет вашу ошибку, используя тот факт, что locale
tolower
не определен в глобальном пространстве имен.
В зависимости от вашей ситуации locale
tolower
может заслуживать рассмотрения. Вы можете найти сравнение tolower
здесь: Какой из них в С++?
К сожалению 1 зависит от cctype
tolower
, который определяется в глобальном пространстве имен. Давайте посмотрим, почему это может быть не так:
Вы справедливо используете #include <cctype>
, так как #include < ctype.h >
устарел в С++: http://en.cppreference.com/w/cpp/header
Но стандарт С++ указывает в D.3 [des.c.headers] 2 объявления в заголовках:
Неизвестно, объявлены или определены ли эти имена в области пространства имен (3.3.6) пространства имен
std
и затем они вводятся в область глобального пространства имен с помощью явных использования-деклараций (7.3. 3)
Таким образом, единственный способ гарантировать наш код - независимость от реализации - использовать tolower
из namespace std
. 2 - это решение, предлагаемое Дэвидом Родригесом - дрибеасом. Он использует тот факт, что static_cast
может:
Используется для устранения неоднозначности перегрузок функций путем преобразования функции в указатель для определенного типа
Прежде чем двигаться дальше, позвольте мне прокомментировать, что если вы обнаружите, что int (*) (int)
немного запутанно, вы можете больше узнать о синтаксисе указателя функции здесь.
К сожалению, есть еще одна проблема с помощью tolower
, если он:
Не представляется без знака char и не равен EOF, поведение не определено
Вы используете строку , которая использует элементы типа:
char
. Стандартные состояния char
в частности 7.1.6.2 [dcl.type.simple] 3:
Определяется реализацией, представлены ли объекты типа
char
в виде подписанных или неподписанных величин. Спецификаторsigned
заставляетchar
объекты подписываться
Итак, если в реализации определен char
означает signed char
, то как 1, так и 2приведет к неопределенному поведению для всех символов, соответствующих отрицательным числам. (Если используется кодировка символов ASCII, символы, соответствующие отрицательным числам, Extended ASCII.)
Неопределенное поведение можно избежать, преобразов вход в unsigned char
, прежде чем передавать его в tolower
. 3 выполняет это, используя lambda, который принимает значение unsigned char
по значению, затем передает его в tolower
, неявно преобразуясь в int
.
Чтобы гарантировать Определенное поведение во всех совместимых реализациях, независимо от кодировки символов, вам нужно будет использовать преобразование (cbegin (s), cend (s), begin (s), [] (const unsigned char i) {return tolower (i);})
или что-то подобное.
Дэвид уже определил проблему, а именно конфликт между:
<cctype>
int tolower(int c)
<locale>
template <typename charT> charT tolower(charT c, locale const& loc)
Использование первого намного проще, но это поведение undefined (к сожалению), как только вы имеете дело с чем-либо еще, чем нижний ascii (0-127) в подписанных символах. Кстати, я рекомендую определять char
как unsigned.
Версия шаблона будет приятной, но вам нужно будет использовать bind
, чтобы предоставить второй параметр, и он должен быть уродливым...
Итак, могу ли я представить Boost String Algorithm m library?
И что еще более важно: boost::to_lower
:)
boost::to_lower(s);
Выразительность желательна.
Просмотр моего заголовка <ctype>
из gcc 4.2.1, я вижу следующее:
// -*- C++ -*- forwarding header.
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
// Free Software Foundation, Inc.
...
#ifndef _GLIBCXX_CCTYPE
#define _GLIBCXX_CCTYPE 1
#pragma GCC system_header
#include <bits/c++config.h>
#include <ctype.h>
// Get rid of those macros defined in <ctype.h> in lieu of real functions.
#undef isalnum
#undef isalpha
...
#undef tolower
#undef toupper
_GLIBCXX_BEGIN_NAMESPACE(std)
using ::isalnum;
using ::isalpha;
...
using ::tolower;
using ::toupper;
_GLIBCXX_END_NAMESPACE
#endif
Таким образом, он выглядит как tolower
существует как в пространствах имен std
(from <cctype>
), так и в корне (из <ctype.h>
). Я не уверен, что делает #pragma
.