2013-03-30 7 views
4

필자는 필터링 된 범위에서 가장 큰 요소로 반복자를 반환하려고합니다. 나는 가장 큰 요소가 벡터 X의 인덱스를 인쇄하는 코드를 예상 C++ : boost :: range를 사용하여 max_element를 찾는 방법?

#include <boost/lambda/lambda.hpp> 
#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 
#include <vector> 
#include <iostream> 

using namespace boost::adaptors; 
using namespace boost::lambda; 
using namespace std; 

int main() 
{ 
    vector<double> x = {100, 150, 200, 110}; 
    auto it = boost::max_element(x | indexed(0) | filtered(_1>100)); /* problem here */ 
    cout << it.index() << endl; 

    return 0; 
} 

(예 2),하지만 불행히도 그것은 컴파일되지 않습니다 (리눅스 64 비트, GCC 4.7 : 여기에 지금까지 무엇을 가지고 .2) 문제는 위에 표시된 줄에 있습니다. 컴파일러에서 얻은 첫 번째 컴파일 오류는 다음과 같습니다.

/boost/tuple/detail/tuple_basic.hpp:396:36 : 오류 : 읽기 전용 멤버 'boost :: tuples : : 단점 : 머리 '

내가 뭘 잘못하고 있는거야? 아니면 내가 뭘 하려는지 어떻게 성취 할 수 있니? 미리 감사드립니다!

편집 :

에 문제가있는 라인을 변경 :

auto it = boost::max_element<boost::return_found>(x | sliced(1,4) | filtered(boost::function<bool(double)>(_1>100))); 

은 큰 요소로 반복자를 반환하는 것 같다. 그러나 iterator가 범위 내에 있는지 확인하는 방법이 있습니까? boost :: end (x)와 비교하면 오류가 발생합니다. 내가 생각할 수있는 유일한 방법은

auto another_range = boost::max_element<boost::return_found_end>(x | sliced(1,4) | filtered(boost::function<bool(double)>(_1>100))); 

을 반환하고 부스트 :: 빈 (another_range) 여부를 확인하는 것입니다. 이것이 유일한 옵션입니까? 감사.

+0

'using' 지시어에주의하십시오.'namespace std'와'namespace boost :: lambda'는'_1'과 같은 자리 표시자가 있습니다. – TemplateRex

+1

@TemplateRex STL 자리 표시자는 네임 스페이스 'std :: placeholders'에 있으므로이 경우에는 충돌이 없습니다. –

답변

4

부스트 람다가 CopyAssignable이 아니기 때문에 특정 오류가 발생했습니다. 여기에 같은 메시지를 달성하는 간단한 방법 : 당신은 당신이 어쨌든 사용한다 filtered, boost.phoenix (에 CopyAssignable 펑터를 제공하는 경우

auto f1 = _1 > 100; 
auto f2 = f1; 
f2 = f1; // same error 

이 boost.lambda는 피닉스에 찬성 중단가는 길에), 손으로 쓴 구조체, 또는 기존의 충실한 std::bind2nd(std::greater<double>(), 100),이 라인은 ++ 연타로 컴파일 :

bind2nd 데모 : http://liveworkspace.org/code/2xKZIf

피닉스 데모 : http://liveworkspace.org/code/18425g

버그 일 가능성이있는 boost.concept 검사로 인해 gcc가 실패하지만 filtered의 결과가 boost::filtered_range이고 이터레이터에 .index() 멤버 함수가 없기 때문에 논점이됩니다.

의견에 대한 응답으로 편집 : iterator를 filtered_range와 비교하여 iterator를 원래 벡터로 비교하는 것은 효과가 없습니다. 그러나, 이후 당신은 벡터를 사용하고, 그것은 여전히 ​​접근 가능하기 때문에,보다 일반적인 솔루션을, 당신은 변환 할 수, 당신은 어느 indexed 이후, 주소를 비교할 수 없으며 filtered가 복사

#include <vector> 
#include <iostream> 
#include <cassert> 
#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 
#include <boost/phoenix.hpp> 

using namespace boost::adaptors; 
using namespace boost::phoenix::placeholders; 

int main() 
{ 
    std::vector<double> x = {100, 150, 200, 110}; 
    auto it = boost::max_element(x | indexed(0) | filtered(arg1 < 110)); 
    assert(&x[0] <= &*it && &*it < &x[0] + x.size()); 
    std::cout << "Element " << *it << " is at index " << &*it - &x[0] << '\n'; 
} 

데모 http://liveworkspace.org/code/1zBIJ9

을 아니면 벡터를 쌍의 벡터로 변환합니다 (부스트가 zip 어댑터를 얻으면 그것은 counting_range로 깔끔하게 압축 될 수 있습니다). 그리고 모든 변환을 통해 값과 함께 원래 시퀀스 인덱스를 전달합니다.

+0

감사합니다. boost :: function을 사용하여 변경 한 내용을 반영하기 위해 원본 게시물을 편집했습니다. 가장 큰 요소에 반복자를 반환하면이 반복자가 범위 내에 있는지 확인하는 방법이 있습니까? 그것을 boost :: end (x)와 비교하면 또 다른 오류가 발생합니다. – linuxfever

+0

대단히 Cubbi 고맙습니다, 지금은 훨씬 더 명확합니다 :) – linuxfever