remove_if(str.begin(),str.end(),:: isspace); :: isspace是什么意思?

时间:2015-03-13 21:25:42

标签: c++ stl

我最近想找到一种使用STL修剪字符串的方法。我看到有人使用

remove_if(str.begin(), str.end(), isspace);

我发现isspace是stl中的一个功能,标题为<ctype.h>。我把上面的代码和头文件放在我的函数中,然后它无法通过编译。编译器抱怨isspace

我试试

remove_if(str.begin(), str.end(), std::isspace);

它仍然无法通过编译。

然后我发现其他人使用

remove_if(str.begin(), str.end(), ::isspace);

我试试这个,它可以通过编译。

我的问题是

  1. 为什么我不能通过前两种方式传递编译。

  2. ::isspace的含义是什么?是否要提及它属于STL或其他什么?我对::的使用感到困惑?

3 个答案:

答案 0 :(得分:5)

std::isspace是C ++中的重载函数,在<locale>中声明了模板函数。允许实现默默地包含您没有要求的其他标题,并且许多标题都是这样做的。他们这样做是因为他们在内部使用这些额外的标题。

通常,传递给std::isspace的参数将决定选择哪个重载,但在您的情况下,您没有传递任何参数,您只是试图仅仅确定其地址。

::isspace有效,因为它不是一个重载函数。

就像

template <typename T>
void f(T) { }

void g(int) { }
void h() { f(g); } // okay, g is not an overloaded function

void i(int) { }
void i(char) { }
void j() { f(i); } // error, the compiler cannot know whether you want the void(int)
                   // function, or the void(char) one

你在评论中被告知的是正确的,确保它有效的简单方法是不要传递isspace的地址,而是创建一个自己的函数来调用{{1} }。无论如何,出于其他原因你需要这样做,但它也很好地完全避免了这个问题。

答案 1 :(得分:3)

::isspace表示您明确调用全局方法isspace。 C标准库方法都是全局变量,<ctype.h>是C标准库标题。

C中不存在命名空间,因此在使用C库头时,不要使用std命名空间。使用std命名空间的<ctype.h>的C ++副本是<cctype>

当您尝试处理名称冲突时,前导::表示法很有用。例如,您可以拥有这样的代码......

void DoSomething(void);

class Foo {
  void DoSomething (void); // Uhoh, this method shadows the global DoSomething.
  void DoSomethingElse(void) {
    Foo::DoSomething(); // Calls the class local DoSomething()
    ::DoSomething(); // Calls the global DoSomething()
  }
};

答案 2 :(得分:0)

请注意,在C ++中,我知道有两个版本的std::ispace函数,即两个重载。其中第一个在<cctype> C兼容性标头中定义为

#include <ctype.h>
namespace std { using isspace = ::isspace; }

其中<ctype.h>是相应的C头,应将isspace(在全局命名空间中,即::isspace)定义为:

int isspace(int);

第二次重载在<locale>中定义为:

namespace std {
  template<class charT> bool isspace(charT, const locale &);
}

如果由于某种原因(直接或间接)包含<cctype><locale>,您将获得std::isspace但有一个全局::isspace函数的两个覆盖。因此,直接使用::isspace会很好,但使用std::isspace会出错,因为编译器无法解决使用哪个重载的歧义。

要解决此问题,您可以通过将函数转换为所需类型来告诉编译器您意味着哪个重载,例如:

std::remove_if(str.begin(),
               str.end(),
               static_cast<int(&)(int)>(std::isspace)); // reference to function
    // Or even static_cast<int(*)(int)>(std::isspace)); // pointer to function

PS:文字::被称为范围解析运算符,因此在A::b的情况下,它引用当前可到达的命名空间b中的A。上下文。如果::前面没有名称,则它引用全局名称空间。有关详细信息,请参阅最新C ++标准草案中的[expr.prim.id.qual]