// // main.cpp // temp // // Created by Joshua Moerman on 9/3/11. // Copyright 2011 Vadovas. All rights reserved. // /* Some helper function to easily iterate over a container of tuples. In particular this is useful with maps. This is meant to be used in range-based for loops. Example: map m = {...}; for(auto & str : keys(m)) cout << str << "\t"; cout << endl; for(auto & i : values(m)) cout << i << "\t"; keys() let you iterate over the keys of a map (the elements returned are const references). values() let you iterate over the values. There is a more general function for any container over tuples: nth_values. Example: vector> v = {...}; for(auto & i : nth_values<2>(v)){ cout << i << endl; ++i; // error: attempting to write to read-only variable // that's because i is a const ref. } That's all :). It's very trivial to just use i.first or get<0>(i), but this might be very handy when debugging or something. */ #include namespace details { /* lazy implementation, relies on inheritance only op* and op-> are overloaded (to return a specific element in the pair or tuple (note that std::get and std::tuple_element are overloaded for pair, to make pair look like a tuple :) ). */ template struct tuple_iterator : public Iterator { tuple_iterator(Iterator it) : Iterator(it) {} typename std::tuple_element::type & operator*(){ return std::get(*(Iterator&)(*this)); } typename std::tuple_element::type & operator->(){ return std::get(*(Iterator&)(*this)); } }; template struct const_tuple_iterator : public Iterator { const_tuple_iterator(Iterator it) : Iterator(it) {} typename std::tuple_element::type const & operator*(){ return std::get(*(Iterator&)(*this)); } typename std::tuple_element::type const & operator->(){ return std::get(*(Iterator&)(*this)); } }; /* The const_iterator is not really needed, since no-one will actually store a const tuple_container_wrapper, but it's here for completeness. */ template struct tuple_container_wrapper { typedef tuple_iterator iterator; typedef const_tuple_iterator const_iterator; tuple_container_wrapper(Container & c) : c(c) {} iterator begin(){ return iterator(c.begin()); } iterator end(){ return iterator(c.end()); } const_iterator begin() const { return const_iterator(c.cbegin()); } const_iterator end() const { return const_iterator(c.cend()); } const_iterator cbegin() const { return const_iterator(c.cbegin()); } const_iterator cend() const { return const_iterator(c.cend()); } private: Container & c; }; template struct const_tuple_container_wrapper { typedef const_tuple_iterator const_iterator; const_tuple_container_wrapper(Container const & c) : c(c) {} const_iterator begin() const { return const_iterator(c.cbegin()); } const_iterator end() const { return const_iterator(c.cend()); } const_iterator cbegin() const { return const_iterator(c.cbegin()); } const_iterator cend() const { return const_iterator(c.cend()); } private: Container const & c; }; } /* nth_values() is the general function to iterate over a specific data element in the container (of tuples/pairs). For map-types there are the functions keys() and values(), which are special cases of this function. */ template details::tuple_container_wrapper nth_values(Container & m) { return details::tuple_container_wrapper(m); } template details::const_tuple_container_wrapper nth_values(Container const & m) { return details::const_tuple_container_wrapper(m); } // NOTE: keys in a map are always const, so a const-only function suffices template details::const_tuple_container_wrapper<0, Map> keys(Map const & m) { return nth_values<0>(m); } template details::tuple_container_wrapper<1, Map> values(Map & m) { return nth_values<1>(m); } template details::const_tuple_container_wrapper<1, Map> values(Map const & m) { return nth_values<1>(m); }