2012-01-16 2 views
1

일반적인 코드를 사용하여 hash_map/unordered_maplist/vector 컬렉션을 반복하는 우아한 솔루션이 있습니까?다른 유형의 컬렉션을 반복하는 공통 코드

예 : 대신 ch->send(head, cnt)ch.second->send(head, cnt) :

template<typename collection> 
class multicast 
{ 
public: 
    typedef collection collection_type; 

private: 
    collection_type& m_channels; 

public: 
    multicast(collection_type& channels) : m_channels(channels) { } 

    void operator()(const buffer::ptr& head, const buffer::ptr& cnt) 
    { 
     for each(collection_type::value_type& ch in m_channels) 
      ch->send(head, cnt); /* this is where the magic should happen? */ 
    } 
} 

이 코드는 분명히 collection_typecollection_type::value_type 이후 unordered_map 때 컴파일에 실패는 실제 값이 달라야에 액세스하십시오 pair 그래서 코드입니다. 그렇다면 중요하지 않은 부분을 제거하는 가장 우아한 방법은 무엇일까요?

+0

템플릿을 부분적으로 특수화 했습니까? – LaC

답변

4

예 : 또는

for (auto & x : collection) { do_stuff_with(x); } 

:

for (auto it = std::begin(collection), end = std::end(collection); it != end; ++it) 
{ 
    do_stuff_with(*it); 
} 

도 범위 기반 forauto 사용할 수 있습니다, 당신은 용기를 필요 템플릿을 작성할 수있는 경우 CC::value_typeC::iterator를 사용; 또는 한쌍의 이터레이터Iter을 허용하고 요소 값 유형으로 std::iterator_traits<Iter>::value_type을 사용하는 템플릿을 만들 수 있습니다.

template <typename T> struct get_value_impl 
{ 
    typedef T value_type; 
    static value_type & get(T & t) { return t; } 
}; 
template <typename K, typename V> struct get_value_impl<std::pair<K, V>> 
{ 
    typedef V value_type; 
    static value_type & get(std::pair<K,V> & p) { return p.second; } 
}; 
template <typename T> 
typename get_value_impl<T>::value_type & get_value(T & t) 
{ 
    return get_value_impl<T>::get(t); 
} 
: 단일 요소와 쌍 요소를 모두 용기를 수용하기

std::for_each(colllection.begin(), collection.end(), 
       [](collection::value_type & x) { do_stuff_with(x); }); 


, 당신은 약간의 래퍼를 구축 할 수 있습니다 :

셋째, 당신은 for_each과 람다를 사용할 수 있습니다

이제 get_value(x) 또는 get_value(*it)을 사용하면 값을 얻을 수 있습니다.

+1

그리고 그는'std :: for_each'를 lambda (C++ 11에서)와 함께 사용할 수 있습니다. – Nawaz

+0

실제로는 'for each'입니다 (범위 기반 루프, vC++ 11) –

+1

질문은 실제 collection-iterating 구문에 대한 것이 아니라 일부 컬렉션에서 제공하는 다른 value_types를 처리하는 방법에 관한 것입니다.일부 콜렉션은 값을주고, 어떤 콜렉션은 키와 값을 제공합니다. –

3

map-s에는 키 - 값 쌍이있는 반면 list/vector에는 값만 들어 있습니다. 그것들은 똑같은 것이 아니며 최소한 당신이 관심있는 쌍의 부분을 정의하는 것과 같은 방식으로 반복 할 수 있습니다.

일단 정의되면 이터레이터를 허용하는 "derefence"연산이 필요합니다. 값 유형에 쌍이있는 경우 두 번째 요소를 반환하고 반대로 참조를 역 참조하십시오.

// default case, returning itself 
template<class T> 
T& get_val(T& t) { return t; } 

// case for pair (derefence for a map iterator) 
template<class K, class V> 
V& get_val(std::pair<const K, V>& s) { return s.second; } 

// iterator dereference 
template<class Iter> 
decltype(get_val(*Iter()) deref_iter(const Iter& i) 
{ return get_val(*i); } 

물론, 필요하면 const_iter 버전도 필요합니다. 이제

:

for(auto i=container.begin(); i!=container-end(); ++i) 
    do_something_with(deref_iter(i)); 

는 어떤 용기 동일합니다.

관련 문제