2011-12-12 3 views
5

나는 람다 함수와 함께 ptr_fun을 사용하는 다음 프로그램을 가지고있다.람다 함수가있는 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

그냥 조금 (!) 참고 : 당신이 하나처럼 람다를 사용하여 계획하는 경우가 여기 많이, 당신은 수도 인수를 참조로 전달하는 것을 고려하십시오. 많은 문자열 복사를 저장하십시오. –

+0

'stringcasecmp' 람다가 재귀적임을 알 수 있습니다! – quamrana

+0

@quamrana 왜 재귀입니까? – ggg

답변

9

bind2nd (§D.9) 및 ptr_fun (§D.8.2.1)은 C++ 11에서 더 이상 사용되지 않습니다. 당신은 find_if 다른 람다 함수를 작성할 수

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

ptr_fun(<lambda>) 작동하지 않습니다, C++ 03은 다른 어댑터에 대한 함수 객체에 함수 포인터를 변환하는 ptr_fun 설계되기 때문이다. 람다는 이미 함수 객체이므로 ptr_fun은 필요하지 않습니다.

bind2nd은 함수 객체가 람다에서는 true가 아닌 second_argument_typeresult_type을 정의 할 것으로 기대하므로 bind2nd(<lambda>, target)을 쓰는 것도 작동하지 않습니다. not1이 기대

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

그러나, bind는 C++ 03 스타일의 함수 객체를 반환하지 않습니다 : 그것은 bind 결과의 유형을 필요로하지만, C에서 작동하는 일반적인 교체가 11 ++ 존재하지 않는 argument_type 구성원을 정의하십시오. 따라서 최종 표현 것이다 하지 작업

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

. 가장 간단한 해결 방법은 위에 쓴 람다를 사용하는 것입니다.

다른 방법으로, 일반적인 부정을 정의 할 수 있습니다 :

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은 C++ 03에서 다른 어댑터의 함수 객체로 함수 포인터를 변환하도록 설계 되었기 때문에 *'''''ptr_fun ()'는 작동하지 않습니다. *"왜 캡쳐없는 람다는 암시 적으로 함수 포인터로 변환 가능합니까? – ildjarn

+1

@ildjarn : 변환 연산자가 템플릿 인수 공제에 참여하지 않는다고 생각합니다. – kennytm

0

ptr_fun(stringcasecmp) 대신 pointer_to_binary_function<string,string,int>(stringcasecmp)을 시도해보십시오.