2014-09-18 7 views
2

필터링 된 반복기에서 발생하는 문제를 제거한 버전으로 필터를 피하기 위해 다르게 다시 쓰라는 점은 없습니다. 이상하게도 실제 코드에서만 is_sorted이 문제가되는 것 같습니다. 다른 용도로는 잘 작동하는 것 같습니다.필터링 된 범위, lambdas 및 is_sorted

#include <vector> 
#include <boost/range/adaptor/filtered.hpp> 
#include <boost/range/algorithm_ext/is_sorted.hpp> 

int main(int argc, const char* argv[]) 
{ 
    using namespace boost::adaptors; 
    std::vector<int> all = {1,2,3,4,5,6,7,8,9}; 
    auto some = all | filtered([] (int i) { return i % 2; }); 
    return boost::is_sorted(some); 
} 
이 (최신에, 맥 OS X에서) 연타 ++ 3.5 및 G ++ 4.9 모두 컴파일에 실패

:

$ clang++-mp-3.5 -std=c++11 -isystem /opt/local/include/ foo.cc 
In file included from foo.cc:3: 
In file included from /opt/local/include/boost/range/algorithm_ext/is_sorted.hpp:18: 
/opt/local/include/boost/detail/is_sorted.hpp:25:28: error: object of type 
     'boost::filter_iterator<(lambda at foo.cc:9:30), std::__1::__wrap_iter<int 
     *> >' cannot be assigned because its copy assignment operator is 
     implicitly deleted 
    for (; it != last; first = it, ++it) 
         ^
... 

/opt/local/include/boost/iterator/filter_iterator.hpp:106:17: note: copy 
     assignment operator of 'filter_iterator<(lambda at foo.cc:9:30), 
     std::__1::__wrap_iter<int *> >' is implicitly deleted because field 
     'm_predicate' has a deleted copy assignment operator 
     Predicate m_predicate; 
       ^
foo.cc:9:30: note: lambda expression begins here 
    auto some = all | filtered([] (int i) { return i % 2; }); 
          ^

을 나는 std::function 수정 그것은 내 람다를 저장 알고 있지만, 내가 원하는 그 가격을 지불하지 마십시오. std::is_sorted 주위에 사용자 정의 래퍼를 사용하여 문제가 해결되지 않습니다. 이 문제는 다른 사람들 (예 : boost transform iterator and c++11 lambda), 과 관련이있는 것으로 보입니다.하지만 그렇지 않습니다. 적어도 치료법은 여기에 적용되지 않습니다.

감사합니다.

답변

7

내부 is_sorted 시퀀스를 반복하는 데 사용되는 반복기가 복사되므로 인접 요소를 비교하는 데 사용할 수 있습니다. 즉, 실제로 후행 반복자를 증가시키는 데 사용되지는 않지만 filtered의 술어 (즉, 람다)도 복사해야 함을 의미합니다. 이터레이터를 복사하는 다른 알고리즘은 같은 문제를 가질 것이다. adjacent_find.

반복자를 복사하는 알고리즘과 그렇지 않은 알고리즘의 차이점은 "다중 패스"알고리즘이라고하며 반복자 유형이 ForwardIterator을 충족해야하며 후자는 단일 패스이며 InputIterator 만 필요합니다. coerce your lambda to a function pointer using +

auto odd = [] (int i) { return i % 2; }; 
auto some = all | filtered(std::ref(odd)); 

대안은 다음과 같습니다 :

이 솔루션은 람다에게 로컬 범위의 수명을주고 reference_wrapper하여 전달하는 것입니다

auto some = all | filtered(+[] (int i) { return i % 2; }); 

이 있지만, captureless의 람다에서만 작동하고, 잠재적으로 불분명하다.

+0

'+'앞에 무엇이 발생했는지 설명 할 수 있습니까? –

+0

@ 토마스 B. http://stackoverflow.com/questions/18889028/a-positive-lambda-what-sorcery-is-this – ecatmur

+0

완벽한, 고마워요! –