鉴于代码:
#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>)
&#34;未解决的重载功能类型&#34; 是什么意思?
如果我用我写的函数替换tolower
,它就不再是错误了。
答案 0 :(得分:27)
尝试使用::tolower
。这解决了我的问题。
答案 1 :(得分:22)
问题很可能与tolower
的多次重载有关,编译器无法为您选择一个。您可以尝试对其进行限定以选择其特定版本,或者您可能需要提供一个强制歧义的函数指针。 tolower
标题以及<locale>
标题中可以存在<cctype>
函数(多个不同的重载)。
尝试:
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 );
答案 2 :(得分:18)
让我们看一下从最差开始到最佳状态的选项列表。我们会在这里列出它们并在下面讨论它们:
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)
将产生如下错误:
调用
时没有匹配功能transform(std::basic_string<char>::iterator, std::basic_string<char>::iterator, std::basic_string<char>::iterator, <unresolved overloaded function type>)
您获得“未解析的重载函数类型”的原因是tolower
命名空间中有2个std
:
locale
库定义template <typename T> T tolower(T, const locale&)
cctype
库定义int tolower(int)
1 是solution offered by davka。它通过利用全局命名空间中未定义locale
的{{1}}这一事实来解决您的错误。
根据您的情况,tolower
locale
可能值得考虑。您可以在此处找到tolower
的比较:Which tolower in C++?
不幸的是, 1 取决于tolower
在全局命名空间中定义的cctype
。让我们来看看为什么情况可能并非如此:
您正确使用tolower
,因为在{+ C}中已弃用#include <cctype>
:http://en.cppreference.com/w/cpp/header
但是C ++标准在D.3 [depr.c.headers]中声明了标题中的声明:
未指定是在名称空间
#include <ctype.h>
的名称空间作用域(3.3.6)中首先声明或定义这些名称,然后通过显式使用声明(7.3.3)将其注入全局名称空间作用域< / p>
因此,我们可以保证代码与实现无关的唯一方法是使用std
中的tolower
。 2 是solution offered by David Rodríguez - dribeas。它利用static_cast
可以:
用于通过执行到特定类型
的函数到指针转换来消除函数重载的歧义
在我们继续之前,让我评论一下,如果您发现namespace std
有点混乱,您可以阅读有关函数指针语法here的更多信息。
可悲的是one other issue有int (*)(int)
的输入参数,如果是:
无法表示为unsigned char且不等于EOF,行为未定义
您使用的tolower
使用了string
类型的元素。标准状态char
具体为7.1.6.2 [dcl.type.simple] 3:
实现定义了
char
类型的对象是表示为有符号数还是无符号数。char
说明符强制signed
个对象被签名
因此,如果实现将char
定义为char
,那么 1 和 2 都会导致所有字符对应的未定义行为到负数。 (如果使用ASCII字符编码,则与负数对应的字符为Extended ASCII。)
通过将输入转换为signed char
,然后将其传递给unsigned char
,可以避免未定义的行为。 3 使用接受tolower
值的lambda,然后将其传递给隐式转换为unsigned char
的{{1}}。
要保证所有合规实施的定义行为,与字符编码无关,您需要使用tolower
或类似内容。
答案 3 :(得分:6)
大卫已经确定了这个问题,即:
之间的冲突<cctype>
的int tolower(int c)
<locale>
的template <typename charT> charT tolower(charT c, locale const& loc)
使用第一个更容易,但是一旦你处理了签名字符中的低-ascii(0-127)以外的任何内容,就会出现未定义的行为(不幸)。 顺便说一下,我建议将char
定义为无符号。
模板版本会很好,但你必须使用bind
来提供第二个参数,而且它一定很难看......
那么,我可以介绍Boost String Algorith m库吗?
更重要的是:boost::to_lower
:)
boost::to_lower(s);
表达力是可取的。
答案 4 :(得分:4)
从gcc 4.2.1浏览我的<ctype>
标题,我看到了:
// -*- 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
)和root(来自<cctype>
)名称空间中都存在<ctype.h>
。我不确定#pragma
做了什么。