2011-10-24 20 views

cevap

7

Bir sınıf şablonu auto_iterator_impl yazmak ve örtülü true veya false dönüştürülebilir auto_iterator_impl bir örneğini döndüren bir işlev şablonunun auto_iterator, aracılığıyla kullanabilirsiniz: Minimal işlevleri ve göz ile

Bir çalışma uygulaması:

template<typename C> 
struct auto_iterator_impl 
{ 
    C & c; 
    typename C::iterator it; 
    auto_iterator_impl(C & c, typename C::iterator & it) : c(c), it(it) {} 
    operator bool() const { return it != c.end(); } 
    typename C::iterator operator->() { return it; } 
}; 

template<typename C> 
auto_iterator_impl<C> auto_iterator(C & c, typename C::iterator it) 
{ 
    return auto_iterator_impl<C>(c, it); 
} 

Testi kodu:

void test(std::map<int, int> & m, int key) 
{ 
    if (auto x = auto_iterator(m, m.find(key))) 
    { 
     std::cout << "found = " << x->second << std::endl; 
     x->second *= 100; //change it 
    } 
    else 
     std::cout << "not found" << std::endl; 
} 

int main() 
{ 
    std::map<int,int> m; 
    m[1] = 10; 
    m[2] = 20; 
    test(m, 1); 
    test(m, 3); 
    test(m, 2); 

    std::cout <<"print modified values.." <<std::endl; 
    std::cout << m[1] << std::endl; 
    std::cout << m[2] << std::endl; 
} 

Çıktı:

found = 10 
not found 
found = 20 
print modified values.. 
1000 
2000 

Çevrimiçi demo: http://www.ideone.com/MnISh

+0

Sizin örnek * kullanımı * bulmak * sonucunu * mümkün yapmaz? –

+1

@Martin: Bir örnekle eklendi. – Nawaz

7

Eh, bu demektir eğer sana kadar, ne biraz sarmalayıcı hakkında:

template <typename Container> 
inline bool find_element(Container const & c, 
         typename Container::const_iterator & it, 
         typename Container::value_type const & val) 
{ 
    return (it = c.find(val)) == c.end(); 
} 

Kullanımı:

std::vector<int> v; 
std::vector<int>::const_iterator it; 

if (find_element(v, it, 12)) { /* use it */ } 
+0

sekanslar için çalışmıyor ..;) – Nim

+0

Nim: 'std :: find (c.begin(), c.end(), val) ', belki de bir" üzerinde adanmış "kullanan uzmanlık eklemek için bekliyoruz jenerik 'bul 'kullanmalısınız typetrait :-) –

+0

Meh. Yineleyici değişkenini önceden bildirmeniz gerekir. Brrr! ;-) –

0

'ü yapmak için bir sarıcı işlevi uygulayabilirsiniz.

#define map_find_if(iterator, container, func) \ 
    auto (iterator) = (func); \ 
    if ((iterator) != (container).end()) 

böyle kullanın:çek sizin için, ya da böyle bir makro kullanarak bunu yapmak için önişlemci kullanabileceği bir temizleyici uygulama olsa bir işlev kullanma

map_find_if(iter, map, map.find(key)) { 
    // found the key 
} 
// else clause could go here 

olasılıkla gerçek değildir ve "C++ yolunda" daha fazla.

+0

Aksini yapabileceğiniz zaman makro kullanmayın, gerçekten: x –

1

o

template<class Iterable> 
bool CheckIterator(const typename Iterable::iterator& iter, const Iterable& collection) 
{ 
    return !(iter == collection.end()); 
} 

gibi bir sarıcı yazmak ve yanı sıra bu kapların diğer türleri ile (örneğin, vektör en) de kullanılabilir, bu

map<int,string> m; 
    m[1]="hello"; 
    m[2]="world"; 
    map<int,string>::iterator it = m.find(2); 
    if(CheckIterator(it,m)) 
    { 
     cout<<it->second; 
    } 

kullanımı en esnek karar olduğunu düşünüyorum
+0

Bu gerçekten çok güzel bir düşük teknoloji ürünü olan bir çözüm olabilir :-) (Her ne kadar farklı bir isim olsa da.) –

1

Bu nasıl? Ben x o zaman, yineleyici gerek aslında sadece değer değil mi boost::optional<val_t> olabilmesi için sorun yok yani eğer bir referans Tamam olduğunu tahmin ediyorum

BOOST_FOREACH(auto &x : c.equal_range(...)) { 
    // x is a val_t &, or const if c is const. 
} 

.

kullanabilirsiniz bir C++ 11 aralık tabanlı bir boost::iterator_range yerine (Ne equal_range döner olan) std::pair a kullanırsanız yerine BOOST_FOREACH ait döngü için.

+0

' c.equal_range (t) ' Aksi takdirde insanların aralıkları yönlendirme çabalarını alkışlarım :) –

+0

@Matthieu: iyi bir çağrı, bunu tamamen özledim! –

0

Kodunuzu anonim bir işleve bölmek istiyorsanız (zaten auto kullanıyorsunuz, C++ 11 varsayılıyor gibi görünüyor)?

#include <iostream> 
#include <map> 

template <typename Container, typename ExecF> 
void exec_if(Container const& cont, typename Container::const_iterator it, ExecF f) 
{ 
    if (it != cont.end()) 
    f(); 
} 

int main(void) 
{ 
    std::map<int, int> bar; 
    bar.insert(std::make_pair(1, 1)); 
    bar.insert(std::make_pair(2, 2)); 
    bar.insert(std::make_pair(3, 3)); 

    auto it = bar.find(2); 
    exec_if(bar, it, [&it]() 
    { 
     std::cout << it->first << ' ' << it->second << std::endl; 
    }); 

} 

DÜZENLEME: şimdi bunun çok daha temiz bir olduğunu düşünüyorum

İlgili konular