使用类成员函数作为比较器

时间:2016-04-24 17:09:35

标签: c++

所以我试图在一个类中添加一个函数来比较两个std::string,忽略这里的情况:Case insensitive standard string comparison in C++

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

class foo {
    public:
        bool icompare_pred(char a, char b) {
             return std::tolower(a) == std::tolower(b);
        }
        bool icompare( string a,  string  b){
            return  equal( a.begin(),  a.end(),  b.begin(),  icompare_pred);
        }
};  

int main() {

}

代码没有编译,甚至更多:它将我发送到STL的深度并出现错误

[Error] must use '.*' or '->*' to call pointer-to-member function in '__binary_pred (...)', e.g. '(... ->* __binary_pred) (...)'

在这部分

stl_algobase.h
 template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
inline bool
equal(_IIter1 __first1, _IIter1 __last1,
  _IIter2 __first2, _BinaryPredicate __binary_pred)
{
  // concept requirements
  __glibcxx_function_requires(_InputIteratorConcept<_IIter1>)
  __glibcxx_function_requires(_InputIteratorConcept<_IIter2>)
  __glibcxx_requires_valid_range(__first1, __last1);

  for (; __first1 != __last1; ++__first1, ++__first2)
if (!bool(__binary_pred(*__first1, *__first2)))
  return false;
  return true;
}

好吧,我该怎么办?如何解决此错误?

4 个答案:

答案 0 :(得分:2)

你应该使用静态函数作为谓词:

static bool icompare_pred(char a, char b) {
^^^^^^

或者您可以使用lambda:

bool icompare( string a,  string  b){
     return  equal( a.begin(),  a.end(),  b.begin(),  
                      [](char a, char b){return std::tolower(a) == std::tolower(b);});
 }

答案 1 :(得分:2)

使icompare_pred()成为foo

的静态函数
    static bool icompare_pred(char a, char b) {
 // ^^^^^^
         return std::tolower(a) == std::tolower(b);
    }

或将该函数移出类foo作为自由函数。

答案 2 :(得分:1)

您需要比较器为static

static bool icompare_pred(char a, char b) {
    return std::tolower(a) == std::tolower(b);
}

此外,由于icompare不是静态的,您必须从foo实例调用它,就像这样

int main()
{
    foo f;
    std::cout << f.icompare("TEST", "test");
}

Live demo,输出

1

答案 3 :(得分:1)

您的代码中存在多个错误,其中一些错误显然未被编译器捕获(由于其允许性?)。例如,icompare_pred本身不是有效的C ++表达式。非静态成员函数名本身不会在C ++中形成有效的表达式。您必须使用()运算符调用该函数,或使用&运算符和限定名称形成指向它的指针。您要做的事情将正确表达为

bool icompare( string a,  string  b){
  return  equal( a.begin(),  a.end(),  b.begin(), &foo::icompare_pred);
}

&运算符和foo::前缀都是必需的。

这就是我们遇到第二个错误的地方。双参数非静态成员函数实际上具有三个参数:您明确声明的两个参数和一个隐式this参数。因此,在您的代码中,您传递的是三参数函数,其中需要一个双参数函数。这是“解释”此错误的一种方法。

为了使您的成员函数可用作std::equal的谓词,您可以“绑定”隐式this参数 - 将特定的固定值附加到它 - 从而将三参数函数转换为一个双参数的。例如

bool icompare( string a,  string  b){
  return  equal( a.begin(),  a.end(),  b.begin(),  
    std::bind(&foo::icompare_pred, this, 
      std::placeholders::_1, std::placeholders::_2));
}

这应该按照预期编译和工作。

但是,由于您的比较谓词并不真正需要或关心该隐式this参数,更好的方法是完全摆脱它:只需将比较器声明为static,如建议的那样在其他答案。如果您这样做,&foo::icompare_pred语法也将变得不必要,您将能够像原始代码一样使用icompare_pred