2013-05-22 3 views
0

반복자를 사용하여 두 개의 컬렉션을 반복하고, 다른 컬렉션과 관련된 (충분히 복잡한) 알고리즘을 기반으로 반복 컬렉션을 수정하고 싶습니다.하나 이상의 컬렉션을 반복하면서 반복자에 쓰기.

#include <iostream> 
#include <vector> 
#include <boost/foreach.hpp> 
#include <boost/range/combine.hpp> 
#include <boost/tuple/tuple.hpp> // tie 
using namespace std; 
using namespace boost; 

int main(void) { 
    // input data; never mind how these get filled 
    int aa[] = {2, 3, 5, 8, 13, 21}; 
    int bb[] = {1, 0, 1, 1, 0, 1}; 
    vector<int> a (&aa[0], &aa[sizeof(aa)/sizeof(aa[0])]); 
    vector<int> b (&bb[0], &bb[sizeof(bb)/sizeof(bb[0])]); 

    // output storage; assume it has always correct dim. 
    vector<int> c (a.size()); 

    // iterate through two coll., reading from both 
    int p, q; 
    BOOST_FOREACH (tie(p,q), combine(a,b)) { // loop1 
    cout << p << "*" << q << "=" << p*q << endl; 
    } 

    // iterate through one coll., writing to it 
    BOOST_FOREACH (int& r, c) { // loop2 
    r = 42; 
    } 

    // iterate through two coll., reading from one, writing to the other? 
    BOOST_FOREACH (??? p, s ???, combine(a,c)) { // loop3 
    s = p * 2; 
    } 

    return 0; 
} 

가 어떻게이 ???의 사이 부분을 선언 (또는 기타 루프 3의 매개 변수 변경) 할 : 다음과 같은 최소한의 예를 고려?

+0

- 특히, 당신은 당신이 정말로 무슨 말을 하려는지 설명하기 때문에 거의 완료했습니다 세 번째 루프를 완성하려면 지금 당장은 견고한 답을 제공하는 것이 불가능합니다. 나는 대답을했지만 WRT는 세 번째 루프를 WRT 한 것입니다. 정말로 원한다. –

답변

1

zip_range의 값 유형은 요소에 대한 참조의 튜플은 다음과 같습니다

#include <iostream> 
#include <vector> 
#include <boost/range.hpp> 
#include <boost/range/combine.hpp> 
#include <boost/tuple/tuple.hpp> 
#include <boost/foreach.hpp> 

int main(int ac,char* av[]) 
{ 
    // input data; never mind how these get filled 
    int aa[] = {2, 3, 5, 8, 13, 21}; 
    int bb[] = {1, 0, 1, 1, 0, 1}; 
    std::vector<int> a(boost::begin(aa), boost::end(aa)); 
    std::vector<int> const b(boost::begin(bb), boost::end(bb)); 

    // output storage; assume it has always correct dim. 
    std::vector<int> c (a.size()); 

    typedef boost::tuple<int const&, int&> val_t; 
    BOOST_FOREACH(val_t const& v, boost::combine(a, c)) { 
    v.get<1>() = v.get<0>() * 2; 
    } 
} 
심각한 정리를 사용할 수 귀하의 질문은
+0

그래서 단서는 한 쌍의 참조를 초기화 할 수 없으므로 한 쌍을 얻은 다음 반환하는 참조를 사용한다는 것입니다. (이 질문에 대한 앞으로의 독자들을 위해서 : 하나는 또한 int & s = v.get를 선언 할 수있다. <1>();') – RolKau

+0

이것은 "둥근 못을 사각 구멍에 넣기에 충분히 큰 망치"라고 나를 비난한다. –

0

IMO, 당신은 거의 충격적인 정도로 BOOST_FOREACH을 과용하고 있습니다. std::foreach처럼 이것은 마지막 알고리즘 중 하나 여야합니다.

세 번째 루프는 거의 std::transform을 사용하여 작성해야합니다. 입력 범위를 가져 와서 변환하고 출력 범위에 결과를 저장하기위한 것입니다 (또는 두 개의 입력 범위를 사용하여 결합하고 BOOST_FOREACH를 처음 사용하는 경우처럼 결과를 세 번째로 넣기위한 것입니다). 이 사용

가, 세 번째 루프과 같이 나온다 : 두 번째에 관해서는

// c[i] = a[i] * 2, i = 0..N-1 
std::transform(begin(a), end(a), begin(c), [](int i) { return i * 2; }); 

을 당신이 정말로 std::fill_n을 원하는 것처럼, 그것은 보인다.

std::fill_n(begin(c), end(c), 42); 

지금, 그것은 범위에 따라 뭔가 (예를 들어, Boost Range의 알고리즘) 하나의 매개 변수를 사용하여 각 begin(X), end(X) 쌍을 교체하여이 조금 간단하게 만들 수있는 것은 사실입니다. 그럼에도 불구하고, 이것들은 BOOST_FOREACH 버전에 비해 훨씬 우수합니다 (tiecombine). 둥근 구멍으로 사각 못을 시도하십시오.

+0

당신은 쉽게 충격을받습니다 ... ;-) 만약 알고리즘이 주변의 문맥을 필요로한다면 문맥을 지닌 객체로 모든 것을 리팩터링하는 것보다 간단한 루프를 사용하는 것이 더 읽기 쉽습니다 - 저는 이것이 대소 문자 의존적이라고 생각합니다. 여기의 예제는 문제를 설명하기위한 것입니다. – RolKau

+0

@RolKau : 루프가 합리적인 대안이 될 수있는 경우도 있지만 솔직히 꽤 이상합니다. 여기에 그런 사례를 보여주지 않았습니다. –

관련 문제