2011-12-12 77 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)