2010-06-24 3 views
3

그냥 재미있게 std :: find_if로 boost :: bind를 사용하여 한 줄을 작성하려고했는데 벡터에있는 모든 키가 있는지 확인합니다 지도에는 값이 없지만 실제로는 깔끔한 코드 줄을 만들 수 없습니다. 여기
내가 사람이 같은 시도 ...<string> 벡터에 값이 없는지 확인하려고합니다. <string, string>

vector<string> v; 
v.push_back("a"); 
v.push_back("2"); 
... 
map<string, string> m; 
m.insert("b","f"); 
... 
std::find_if(v.begin(), v.end(), boost::bind(&string::empty, boost::bind(&map<string,String>::operator[], _1), _2)) != v.end(); 

은 분명히이 큰 실패한다 시도 무엇인가?

답변

5

v의 모든 요소는 m에 존재하지 않는 경우에만 :

bool a = v.end() == std::find_if(v.begin(), v.end(), boost::bind(&str_map_t::const_iterator::operator!=, boost::bind<str_map_t::const_iterator>(&str_map_t::find, &m, _1), m.end())); 

설명 : 여기에

는 우리가 두 개의 펑터 :

  1. boost::bind<str_map_t::const_iterator>(&str_map_t::find, &m, _1)
    이 functor는 m 또는 찾을 수없는 경우 m.end()의 요소를 가리키는 const_iterator을 반환합니다. 여기서 명확하게 반환 유형 str_map_t::const_iteratorboost::bind으로 지정하여 모호성을 없애야합니다.

  2. boost::bind(&str_map_t::const_iterator::operator!=, _1, _2)
    이 사람은 true 그렇지 않으면 _1!=_2false 경우 반환합니다.

1 결합 및 2 그리고 우리는 전체 코드 얻을 것이다 :

#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <iterator> 
#include <string> 
#include <map>  
#include <boost/bind.hpp>  
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    vector<string> v; 
    v.push_back("x"); 
    v.push_back("a"); 
    v.push_back("6"); 

    typedef map<string, string> str_map_t; 
    str_map_t m; 
    m.insert(str_map_t::value_type("b", "f")); 

    bool a = 
     v.end() == std::find_if( 
     v.begin(), v.end(), 
      boost::bind( 
      &str_map_t::const_iterator::operator!=, 
      boost::bind<str_map_t::const_iterator>(&str_map_t::find, &m, _1), 
      m.end() 
     ) 
    ); 

    std::cout << a << endl; 

    return 0; 
} 

내가 그것을 읽을 수있는 코드이며 나는 그것을 더 얻을 수있는 사용자 정의 펑터를 쓸 것을 권 해드립니다 언급하지 않았다을 읽을 수있는. 더 읽을 버전 (bind없이)는 다음과 같이 수 :

나는 모든 좋아한다
struct not_in_map { 
    not_in_map(const str_map_t& map) : map_(map) {} 
    bool operator()(const string& val) { return map_.end() != map_.find(val); } 
private: 
    const str_map_t& map_; 
}; 
bool a = v.end() == std::find_if(v.begin(), v.end(), not_in_map(m)); 
+2

예, 그런 코드는 일광을 보게하지만 여전히이 멋진 기능을 배우고 싶습니다. 좋은 답변 주셔서 감사합니다. – SWKK

5
std::for_each(v.begin(), v.end(), [](std::string& ref) { if m.find(ref) != m.end() /* do something*/ }); 

람다스 ftw.

+0

답변 - 슬프게도 다른 통해 하나를 선택해야합니다. 나는 람다를 좋아하지만 이번에는 좀 더 포괄적 인 다른 대답이 내 표를 얻습니다. :) – SWKK

+2

하지만 그의 대답은 한 줄의 코드가 아닙니다! – Puppy

+1

현재 C++ 표준이 람다 함수를 지원하지 않기 때문에 코드가 컴파일되지 않습니다. –

1

boost :: lambda는 C++ 0x와 기능적 프로그래밍을위한 다른 유용한 메커니즘이 언어의 일부가 될 때까지 최선의 방법입니다. 그러나 팀에서 일하면 코드를 조금 어리 석으라고 권장합니다.

간결하고 간결한 코드는 펑터, 술어 등을 이해하지 못하는 경험이 거의없는 C++ 코드 작성자에게 많은 골칫거리를줍니다. 그런 경우에도 디버깅을 시도 할 때 두통을 줄 수 있습니다 코드는 분산 환경으로 인해 발생합니다. C++의 모든 기능적인 측면을 희생해야만했습니다. 작업하는 팀의 전반적인 이익을 위해 반복자가있는 for 루프를 사용하는 것이 좋습니다. 아마도 C++ 0x에서는 다른 프로그래머가 함수 프로그래밍을 사용하면서 제기 한 문제를 쉽게 이해할 수있을뿐 아니라 많은 사람들이 (불행히도) 싫어하는 복잡한 템플릿 메커니즘없이 충분히 완화 될 수 있습니다. 다음의 코드는 true을 반환

관련 문제