0

如果以前有人问过这个问题,请原谅我,我只是找不到合适的解决方案。

我经常发现自己为类的成员函数创建仿函数,如下所示,然后用于 find_if 或 remove_if

class by_id{
  public:
    by_id(int id):mId(id) {}

    template <class T>
    bool operator()(T const& rX) const { return rX.getId() == mId; }

    template <class T>
    bool operator()(T* const pX) const { return (*this)(*pX); }

  private:
    int mId;
};

虽然这很好用,但它包含很多样板文件,并且意味着为我想用于比较的每个成员函数定义一个类。

我知道 C++11 中的 lambda,但由于交叉编译器的限制,我无法切换到新标准。

我发现的最接近的相关问题是stl remove_if with class member function result但给定的解决方案意味着添加额外的成员函数进行比较,这很难看。

有没有更简单的方法使用标准 STL 或 boost 以更通用的方式编写此类函子或使用 bind 完全跳过它们?

像通用函子之类的东西会做,但我缺乏编写它的技能。只是为了弄清楚我的想法:

  template<typename FP,typename COMP>
  class by_id{
      public:
        by_id(COMP id):mId(id) {}

        template <class T>
        bool operator()(T const& rX) const { return rX.FP() == mId; } 
        //of course this does not work

        template <class T>
        bool operator()(T* const pX) const { return (*this)(*pX); }

      private:
        COMP mId;
    };
4

3 回答 3

2

如果您T提前知道(在创建by_id对象时,您可以将其作为模板参数by_id并将指向成员函数的指针传递给构造函数。例如:

template<typename T, typename COMP>
class by_id
{
 public:
  typedef COMP (T::*MemFunc)();
  by_id(COMP id, MemFunc mf) : mId(id), mmf(mf) {}

  bool operator()(T const& rX) const { return rX.*mmf() == mId; }

 private:
  COMP mId;
  MemFunc mmf;
};
于 2012-05-19T10:36:41.527 回答
1

您可以将成员函数指针传递给比较器以指示要比较的值。

使用make_comparer函数避免在使用点指定类型参数(类似于std::make_pair

#include <iostream>
#include <vector>
#include <algorithm>

template<typename T, typename R>
class comparer
{
public:
    typedef R ( T::*accessor_type ) () const;
    typedef R value_type;
    comparer ( accessor_type accessor, value_type value ) :
        accessor_ ( accessor ), value_ ( value ) { }

    accessor_type accessor_;
    value_type value_;

    bool operator() ( T const& rX ) const {
        return ( rX.*accessor_ ) () == value_;
    }
    bool operator() ( const T* pX ) const {
        return ( *this ) ( *pX );
    }
};

template <typename T, typename R>
comparer<T, R> make_comparer ( R ( T::*accessor ) () const, R value )
{
    return comparer<T, R> ( accessor, value );
}

class Foo
{
public:
    explicit Foo ( int id, int rank ) : id_ ( id ), rank_ ( rank ) { }
private:
    int id_, rank_;

public:
    int id() const {
        return id_;
    }
    int rank() const {
        return rank_;
    }

};

std::vector<Foo> foos;
typedef std::vector<Foo>::const_iterator FooIT;

void print ( FooIT it )
{
    if ( it == foos.end() )
        std::cout << "no match" << std::endl;
    else
        std::cout << "matches id: " << it -> id () << " rank: " << it -> rank () << std::endl;
}

main()
{

    foos.push_back ( Foo ( 1, 3 ) );
    foos.push_back ( Foo ( 2, 2 ) );
    foos.push_back ( Foo ( 3, 1 ) );

    std::cout << "compare id == 2 ";
    print ( std::find_if ( foos.begin(), foos.end(), make_comparer ( &Foo::id, 2 ) ) );

    std::cout << "compare id == 3 ";
    print ( std::find_if ( foos.begin(), foos.end(), make_comparer ( &Foo::id, 3 ) ) );

    std::cout << "compare rank == 3 ";
    print ( std::find_if ( foos.begin(), foos.end(), make_comparer ( &Foo::rank, 3 ) ) );
}
于 2012-05-19T10:41:13.630 回答
1
using namespace boost;
std::find_if(first, last, bind(std::equal<int>(), bind(&Foo::getId, _1), id));

这将创建一个嵌套的绑定表达式并为 range 中的每个元素调用它[first,last),其中为元素调用绑定表达式Foo i等效于调用:

std::equal<int>()( i.getId(), id )

即它测试是否i.getId()等于id

在 C++11 中,您可以替换boost::bindstd::bind

using namespace std::placeholders;
std::find_if(first, last, std::bind(std::equal<int>(), std::bind(&Foo::getId, _1), id));
于 2012-05-19T16:55:45.177 回答