I have the following program that uses ptr_fun with a lambda function.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int main()
{
string target="aa";
vector<string> v1;
v1.push_back("aa");
v1.push_back("bb");
auto stringcasecmp=[](string lhs, string rhs)->int
{
return strcasecmp(lhs.c_str(), rhs.c_str());
};
auto pos = find_if(
v1.begin(), v1.end(),
not1( bind2nd(ptr_fun(stringcasecmp), target) )
);
if ( pos != v1.end())
cout << "The search for `" << target << "' was successful.\n"
"The next string is: `" << pos[1] << "'.\n";
}
I get the following error messages.
stackoverflow.cpp: In function ‘int main()’:
stackoverflow.cpp:21:41: error: no matching function for call to ‘ptr_fun(main()::<lambda(std::string, std::string)>&)’
stackoverflow.cpp:22:6: error: unable to deduce ‘auto’ from ‘<expression error>’
How do i amend the code (minimally) to make it compile?
bind2nd
(§D.9) and ptr_fun
(§D.8.2.1) are deprecated in C++11. You could just write another lambda function in find_if
:
auto pos = find_if(v1.begin(), v1.end(),
[&](const std::string& s) {
return !stringcasecmp(s, target);
});
ptr_fun(<lambda>)
will not work, because ptr_fun
is designed for C++03 to convert a function pointer to a function object for other adaptors. A lambda is already a function object, so the ptr_fun
is unnecessary.
bind2nd
expects the function object to define the members second_argument_type
and result_type
, which is not true for a lambda, so writing bind2nd(<lambda>, target)
won't work either. But in C++11 there is a generic replacement that works:
std::bind(stringcasecmp, std::placeholders::_1, target)
However, bind
does not return a C++03-style function object, which not1
is expecting: it requires the type of result of bind
to define the argument_type
member which does not exist. Therefore the final expression
std::not1(std::bind(stringcasecmp, std::placeholders::_1, target))
will not work. The simplest workaround is just use another lambda I've written above.
Alternatively, you could define a generic negator:
template <typename Predicate>
struct generic_negate
{
explicit generic_negate(Predicate pred) : _pred(pred) {}
template <typename... Args>
bool operator()(Args&&... args)
{
return !_pred(std::forward<Args>(args)...);
}
private:
Predicate _pred;
};
template <class Predicate>
generic_negate<Predicate> not_(Predicate pred)
{
return generic_negate<Predicate>(pred);
}
....
auto pos = find_if(v1.begin(), v1.end(), not_(bind(stringcasecmp, _1, target)));
Example: http://ideone.com/6dktf
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With