【问题标题】:std::isgraph is ambiguous when `using namespace std` is used当使用 `using namespace std` 时,std::isgraph 不明确
【发布时间】:2016-02-27 17:49:57
【问题描述】:

我尝试使用来自<cctype>std::isgraph 作为find_if 中的谓词。但是编译器错误地说:

错误:没有匹配函数调用 'find_if(__gnu_cxx::__normal_iterator >, __gnu_cxx::__normal_iterator >, 未解决的重载函数类型>)'

我使用了using namespace std;,据我了解,在全局命名空间中将有两个isgraph 函数可见。所以::isgraph 或简单的isgraph 应该是模棱两可的,std::isgraph 不应该是模棱两可的。相反,使用::isgraph 可以,而std::isgraph 则不行。

谁能解释我错过了什么?一些相关问题是What are the function requirements to use as the predicate in the find_if from the <algorithm> library?C++ using standard algorithms with strings, count_if with isdigit, function cast。但他们没有回答为什么明确指定 std:: 仍然无法解析到 std 命名空间中的函数。

编辑

#include <cctype>
#include <algorithm>
#include <string> 
#include <iostream> 
using namespace std;

int main()
{   
   string root_line = "hello";
   auto ind = distance(root_line.begin(), find_if(root_line.begin(), root_line.end(), std::isgraph));

   cout << ind;

   return 0;
}

我用4.8.4版本的g++ -std=c++11编译了上面的代码

【问题讨论】:

  • 你能举几个我可以编译和玩的例子吗?
  • 它对我有用,所以这很奇怪。
  • @Rich 这在 VS2015 中完全有效,但似乎在其他任何地方都没有。
  • 如果你去掉 using 并把 std:: 放在前面,错误仍然存​​在,所以这是一个红鲱鱼。
  • @NeilKirk 哇,谢谢! cppreference 自己的搜索未在 标头中显示该搜索。这解决了这个谜。

标签: c++


【解决方案1】:

std::isgraph 过载。

要解决歧义,您可以将其转换为相关的函数指针类型。

但为了正确使用它,参数应该转换为unsigned char,所以最好定义一个包装函数:

using Byte = unsigned char;

auto is_graphical( char const ch )
    -> bool
{ return !!isgraph( Byte( ch ) ); }

请注意,这仅适用于单字节编码,并且取决于 C 级别的当前语言环境(请参阅setlocale)。

【讨论】:

  • std::isgraph 过载了吗?它的另一个签名是什么?我怎么在 cppreference 上找不到呢?
  • @Rich:我想我可能在这里犯了错误。错误消息说它因 OPs C++ 实现而过载。并且有一个std::graph 函数模板。但到目前为止,我找不到可以专门用于charwchar_t 的信息。检查...谢谢!
  • 好的,事实证明答案文本在技术上是正确的。同名的函数模板足以阻止成功的重载解析。我在这里怀疑自己,认为具体功能应该胜过模板,但我错了,认为我错了。嗯。
【解决方案2】:

&lt;cctype&gt; 中定义了一个std::isgraph,在 中定义了一个不同的std::isgraph。使用重载函数作为仿函数可能会很痛苦,因为编译器很难确定你想要哪个版本的函数。您可以按照@Cheersandhth.-Alf 的建议,通过强制转换或使用 lambda 或命名包装函数来解决歧义。-Alf

#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>

int main()
{   
   std::string root_line = "hello";
   auto ind = std::distance(root_line.begin(), std::find_if(root_line.begin(), root_line.end(), static_cast<int(*)(int)>(std::isgraph)));
   std::cout << ind;
}

现场示例:http://ideone.com/heSSEZ

【讨论】:

  • 尼尔,你是多年前的尼尔吗?
  • 标头 是否以某种方式被其他标头包含在内?有没有办法找出哪些头文件包含某个其他头文件(如果可能的话,除了查看源代码)?
  • @Cheersandhth.-Alf 可能,我成为尼尔已经有一段时间了。你能详细说明一下吗?
  • @NeilKirk:对不起,我想我把你和 Neil Butterworth 搞混了。他是备受瞩目的"I'm leaving Stack Overflow" users 之一。 '轨道竞赛,链接到我也离开文章的作者,回来了。我以为你可能是回来的巴特沃斯尼尔。在某种程度上,这是一种恭维。 IIRC,在 NB 离开很久之后,人们可以将他的答案识别为高度赞成的无用户名答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 2011-09-22
  • 1970-01-01
  • 2017-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多