find_if 在 vector<Message*> 上,带有 bind2nd 和函子

find_if on vector<Message*> with bind2nd and functor

本文关键字:带有 bind2nd gt Message if vector find lt      更新时间:2023-10-16

我有一个这样的向量:

typedef vector<Message*> OmciMessages;
OmciMessages omciResponses;

我有一个像下面这样的函子,我怀疑它是不正确的:

class isMatching{
public:
    bool operator()(const Message* responseMsg,unsigned short transactionid){       
        return responseMsg->getTransactionId()==transactionid;
    }
};

然后我调用find_if,并希望使用函子在向量中找到一些东西,但只针对类中的特定事务id:

OmciMessages::iterator responseit 
    = find_if(omciResponses.begin(),
              omciResponses.end(),
              bind2nd(isMatching(),transactionid));

编译器不喜欢它,并且会产生很多错误消息,这些错误消息通常很难解释为模板类。

/repo/stuyckp/ngpon2WW/tools/cm4/tools/GNU/src/gcc/i686-pc-linux-gnu/bin/../lib/gcc/i686-pc-linux-gnu/3.4.6/../../../../../include/c++/3.4.6/bits/stl_function.h:429: error: no type named `first_argument_type' in `class isMatching'

如果我在没有函数对象的情况下这样做,它会起作用:

static bool isMatching(Message* responseMsg){
    return responseMsg->getTransactionId()==transactionid;
}
transactionid = 5; //global variable being used. yuck, don't like it
find_if(omciResponses.begin(),
        omciResponses.end(),
        isMatching);

但后来我需要一个预先设置的全局变量事务id,我认为这不是一个好的设计。那么,bind2nd方法应该如何做到这一点呢?

给定编译器的版本,我假设C++11不是一个选项(否则答案很简单:使用lambda(。

旧的函数对象绑定器(在C++11中已弃用,在C++17中已删除(需要一堆嵌套的typedef。您需要将result_typefirst_argument_typesecond_argument_type定义为isMatching的成员,可以直接定义,也可以通过binary_function助手(在C++11中也不推荐使用,在C++17中已删除(将其与bind2nd一起使用。

您还可以使用一个带有两个参数的普通函数,将其与ptr_fun进行适配(同样,在C++11中已弃用,在C++17中已删除(,然后与bind2nd绑定。

或者只使用一个有状态函子,如Piotr的回答所示。

bind2nd需要您的函子类具有适应性,即提供某些typedef,包括first_argument_typesecond_argument_typeresult_type。您可以在函数类中自己定义它们,也可以从std::binary_function继承以简化:

class isMatching : public std::binary_function<const Message*, unsigned short, bool> {
public:
    bool operator()(const Message* responseMsg, unsigned short transactionid) const {       
        return responseMsg->getTransactionId() == transactionid;
    }
};
struct isMatching
{
    unsigned short transactionid;
    explicit isMatching(unsigned short transactionid) : transactionid(transactionid) {}
    bool operator()(const Message* responseMsg) const
    {       
        return responseMsg->getTransactionId() == transactionid;
    }
};
std::find_if(omciResponses.begin()
           , omciResponses.end()
           , isMatching(0));
//                      ^ transactionId to be searched for

演示

请注意,如果您希望使用std::bind2nd,或者函数对象将是无状态的,那么您根本不需要将函数对象作为单独的类:

bool isMatching(const Message* responseMsg, unsigned short transactionid)
{
    return responseMsg->getTransactionId() == transactionid;
}
std::find_if(omciResponses.begin()
           , omciResponses.end()
           , std::bind2nd(std::ptr_fun(&isMatching), 0));
//                        ~~~~~~~~~~~^               ^ transactionId to be searched for
//      transform to a function object

演示2