2011-12-12 75 views
5

我有以下使用带有lambda函数的ptr_fun的程序。带有lambda函数的ptr_fun

#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"; 
} 

我收到以下错误消息。

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>’ 

如何修改代码(最低限度)使其编译?

+1

只是一个小旁注:如果您在使用Lambda像一个规划,你这里有很多,你可能考虑传递参数作为参考。节省很多字符串复制。 –

+0

你可能会发现你的'stringcasecmp' lambda是递归的! – quamrana

+0

@quamrana为什么递归? – ggg

回答

9

bind2nd(§D.9)和ptr_fun(§D.8.2.1)在C++ 11中已弃用。你可以只写另一个lambda功能find_if

auto pos = find_if(v1.begin(), v1.end(), 
        [&](const std::string& s) { 
         return !stringcasecmp(s, target); 
        }); 

ptr_fun(<lambda>)将无法​​正常工作,因为ptr_fun是专为C++ 03函数指针转换为其它适配器一个函数对象。 lambda已经是一个函数对象,所以ptr_fun是不必要的。

bind2nd期望函数对象定义成员second_argument_typeresult_type,这对lambda不适用,因此编写bind2nd(<lambda>, target)也不起作用。但在C++ 11有一个通用的替代品,工作原理:

std::bind(stringcasecmp, std::placeholders::_1, target) 

然而,bind不返回一个C++ 03式函数对象,这not1期待:它需要bind结果的类型定义不存在的argument_type成员。因此,最终的表达

std::not1(std::bind(stringcasecmp, std::placeholders::_1, target)) 

工作。最简单的解决方法就是使用上面写的另一个lambda表达式。

或者,你可以定义一个通用的否定符:

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))); 

例子:http://ideone.com/6dktf

+0

谢谢。我认为bind2nd被弃用是很奇怪的,但是C++ 11绑定不能与not1一起工作。 – ggg

+0

“*'ptr_fun()''不起作用,因为'ptr_fun'设计用于C++ 03将函数指针转换为其他适配器的函数对象。*”为什么它不能工作, lambda可以隐式转换为函数指针? – ildjarn

+1

@ildjarn:我不认为转换操作符会参与模板参数推导。 – kennytm

0

尝试pointer_to_binary_function<string,string,int>(stringcasecmp)而不是ptr_fun(stringcasecmp)