问题
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 更愿意在调用时出错,而不是在重载解析失败时出错。 p>
说明
首先,您应该考虑如何在 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 的调用。
差异
现在,那个原始问题的 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
);
-
您可以通过显式使用全局 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])。
因此,这不是我推荐的选项。
(注意:我讨厌把尖括号写成标题名称的一部分——它们是#include语法的一部分,而不是标题名称——但我已经在这里完成了为了与 FDIS 报价保持一致;老实说,它更清晰...)