Sta*_*eem 57 c++ algorithm stl
我尝试了这个问题的代码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;
}
Run Code Online (Sandbox Code Playgroud)
从理论上说,它应该是Josuttis书中的一个例子,但它不编译http://ideone.com/aYnfv.
为什么海湾合作委员会抱怨:
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>)’
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么吗?是GCC相关的问题吗?
Naw*_*waz 70
只需使用::toupper而不是std::toupper.也就是说,toupper在全局命名空间中定义,而不是在std命名空间中定义的命名空间.
std::transform(s.begin(), s.end(), std::back_inserter(out), ::toupper);
Run Code Online (Sandbox Code Playgroud)
它的工作原理:http://ideone.com/XURh7
您的代码无效的原因:toupper命名空间中有另一个重载函数,std在解析名称时会导致问题,因为当您只是传递时,编译器无法确定您所指的是哪个重载std::toupper.这就是编译器unresolved overloaded function type在错误消息中说的原因,它表明存在重载.
因此,为了帮助编译器解决正确的重载,你需要转换std::toupper为
(int (*)(int))std::toupper
Run Code Online (Sandbox Code Playgroud)
也就是说,以下方法可行:
//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);
Run Code Online (Sandbox Code Playgroud)
Lig*_*ica 45
std::transform(
s.begin(),
s.end(),
std::back_inserter(out),
std::toupper
);
Run Code Online (Sandbox Code Playgroud)
没有匹配函数来调用'
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中定义为宏的名称除外)都在命名空间std的命名空间范围(3.3.6)内.未指定是否首先在全局命名空间范围内声明这些名称,然后通过显式using-declarations将其注入命名空间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无法完成您的呼叫.
现在,原始问题的OP没有遇到这个问题.他可能没有std::toupper范围内的语言环境版本,但是你再也没有#include <locale>!
然而:
[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
);
Run Code Online (Sandbox Code Playgroud)您可以通过显式使用global来从重载集中删除语言环境版本toupper:
std::transform(
s.begin(),
s.end(),
std::back_inserter(out),
::toupper // global scope
);
Run Code Online (Sandbox Code Playgroud)
但是,请记住,此函数<cctype>是否可用是未指定的([17.6.1.2/4]),并且<ctype.h>不推荐使用([C.3.1/1]).
因此,这不是我推荐的选项.
(注:我鄙视写尖括号,如果他们头名的一部分-他们的部分#include语法,而不是标题名称-但我引用了在这里做它用FDIS一致性;而且,说实话,这是更清晰...)