2011-09-07 3 views
6

은이 질문은이 질문을 제기하는 another topic에서 영감이다. 일반적인 C++ 03 솔루션은 전용 함수 (또는 펑터)를 정의하고이를 세 번째 인수로 std::find_if에 전달합니다.어떻게하면 몇 가지 부스트 라이브러리를 사용하여 std :: find_if와 std :: map을 함께 사용할 수 있습니까?</p> <blockquote> <p>여러 가지 방법으로 해결 될 수있는지도 컨테이너</p> </blockquote> <p>에서 사용자가 지정한 값보다 첫 번째 큰 값을 찾기 :

는 C++ 11 번이 전용 기능 (또는 펑)을 형성 피할 수 있고, 대신 등 lambda 사용 할 수있다 the accepted answer

auto it = std:: find_if(m.begin(), mp.end(), 
        [n](const std::pair<std::string, int> & x) -> bool 
         { return x.second > n; } 
        ); 

한다.

저는 아직 짧고 멋진 해결책을 찾고 있습니다. 이 벡터 인 경우, 다음 그냥 Boost.Phoenix의 사용을하고 솔루션은 매우 간결하게 멋진 솔루션 (ideone demo) 학습 :

std::vector<int> v = ...; 
auto it = std::find_if(v.begin(), v.end(), arg1 > 4); 
다음 arg1

boost::phoenix::arg_names 네임 스페이스에 정의 된 펑터 객체이며, 식을 arg1>4 다른 functor를 평가 한 후 std::find_if으로 전달됩니다.

빠른 테스트는 (ideone),

std::cout<< (arg1 > 9)(v) << std::endl; //prints 0 if as v > 9 is false, else 1 

//or store the functor first and then use it 
const auto & f = arg1 > 9; 
std::cout<< f(v) << std::endl; //prints 0 if as v > 9 is false, else 1 

내 질문은

, 나는 비슷한 방법으로,지도 문제를 해결하는 것도 중요합니다. 그런 해결책이 있습니까? 같은 뭔가 :

auto it = std::find_if(m.begin(),mp.end(), (???).second > n); //m is std::map 

또는

auto it = std::find_if(m.begin(),mp.end(), at<1>(arg1) > n); //m is std::map 

가 작동하는 경우, 표현 at<1>(arg1) > 2는 인수로 const std::pair & 소요 펑터로 평가한다. 나의 위장 감각은 부스트가이 해결책을 가지고있다라고 나에게 이야기한다. :-)

+0

당신은 값을 (찾을 하시겠습니까 경우에 http : // www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/adaptors/reference/map_values.html이 답)이거나 값 전체가 술어를 만족시키는 값 쌍 전체에 대한 반복자 ? – Cubbi

+0

@Cubbi :지도의 반복자를 반환하는'std :: find_if'와 함께 작동하지 않으면 대답이 아닙니다. – Nawaz

+0

@ Nawaz : std :: find_if가 필요한지 모르겠습니다. 그렇지 않다면, 나는 http://www.cplusplus.com/reference/stl/map/upper_bound/로 가야한다.이 코드는 더 빨라야하며 코드는 단 한 줄 밖에 없다. –

답변

9

사실, Boost.Fusion과 Boost.Phoenix는 원하는 것을 정확하게 내장하고 있습니다.

하나 adapt std::pair<> as a conforming Fusion sequence에 필요한 헤더를 포함하는 경우, 다음 중 하나가 std::pair<>::first 또는 std::pair<>::second이 (#include <boost/phoenix/fusion.hpp>로 확인)에 액세스 할 수 boost::fusion::at_c<>의 피닉스의 게으른 버전을 사용할 수 있습니다.

namespace phx = boost::phoenix; 
using phx::arg_names::arg1; 

auto it = std::find_if(m.begin(), m.end(), phx::at_c<1>(arg1) > n); 

편집 : VC++ 2010 SP1 + 부스트 1.47.0 테스트 전체 샘플 :

#include <algorithm> 
#include <map> 
#include <string> 
#include <iostream> 
#include <boost/fusion/include/std_pair.hpp> 
#include <boost/phoenix/core.hpp> 
#include <boost/phoenix/operator.hpp> 
#include <boost/phoenix/fusion.hpp> 

int main() 
{ 
    namespace phx = boost::phoenix; 
    using phx::arg_names::arg1; 

    std::map<std::string, int> m; 
    m["foo"] = 1; 
    m["bar"] = 2; 
    m["baz"] = 3; 
    m["qux"] = 4; 
    m["quux"] = 5; 
    m["corge"] = 6; 
    m["grault"] = 7; 
    m["garply"] = 8; 
    m["waldo"] = 9; 
    m["fred"] = 10; 
    m["plugh"] = 11; 
    m["xyzzy"] = 12; 
    m["thud"] = 13; 

    int const n = 6; 
    auto it = std::find_if(m.cbegin(), m.cend(), phx::at_c<1>(arg1) > n); 
    if (it != m.cend()) 
     std::cout << it->first << '\n'; // prints "fred" 
} 
+0

전체 작업 및 테스트 솔루션을 게시하십시오. 나는 그것이 컴파일되지 않거나 작동하지 않는다고 말하고 싶지 않습니다. 나는 네가 제안한 것을하려고 노력하고있다. – Nawaz

+0

@Nawaz : 편집 됨. – ildjarn

+0

좋아. 나는 컴파일을 시도했는데 컴파일시에 실패했다. http://ideone.com/EgALC – Nawaz