2015-08-28 60 views
3

矢量 我有一个这样的载体: find_if与bind2nd和函子

typedef vector<Message*> OmciMessages; 
OmciMessages omciResponses; 

而且我有一个像下面的一个函子,我怀疑是不正确的:

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

然后调用find_if并且想要使用仿函数来查找向量中的某些内容,但仅限于我的类中的特定transactionid:

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方法?

+0

'transactionid'是一个全局变量吗?某些方法不是'find_if()'调用的一部分吗? – CinCout

+0

它不再是如果我使用函数,只有当我使用静态isMatching函数我需要全局变量在isMatching函数内使用它。正如你所看到的,transactionid没有在该函数中声明。关键是我想避免这种全球性。 –

回答

1
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 

DEMO

请注意,如果您督促使用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 

DEMO 2

+0

这肯定会起作用,如果我无法获得bind2nd的工作,或者如果该代码太丑,我会使用它。代码很干净,像这样。 –

+0

@PhilipStuyck您可能会对 –

+0

感兴趣的更多更新让我信服。谢谢 –

2

bind2nd需要你的函子类适应性,即提供一定的typedef,包括first_argument_type,second_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; 
    } 
}; 
+1

我认为operator()需要为const才能正确编译? –

+0

@PhilipStuyck是的。 – songyuanyao

+1

这工作完美。我不得不从模板中删除const,所以Message * iso const Message *因为getTransactionId不是const,原因可能不那么明显,因为这是一个getter。你不可能知道这一点。谢谢你为我节省了几个小时的时间。 –

2

鉴于你的编译器的版本,我认为C++ 11不是一个选项(否则答案是简单:使用lambda)。

旧的函数对象绑定器(在C++ 11中不推荐使用,在C++ 17中删除)需要一堆嵌套的typedefs。您需要将result_type,first_argument_typesecond_argument_type定义为isMatching的成员,可以直接或通过binary_function帮助程序(在C++ 11中也弃用,并在C++ 17中删除)与bind2nd一起使用。

您还可以使用带有两个参数的普通函数,并将其与ptr_fun(再次在C++ 11中弃用并在C++ 17中删除)相匹配,然后与bind2nd绑定。

或者只是使用一个有状态函数,如Piotr的答案所示。

+0

我开始认为piotr的解决方案比首先使用bind2nd更好。因为你正在解释所有的贬义。 –