diff --git a/iterators/main.cpp b/iterators/main.cpp deleted file mode 100644 index 7b9f8d0..0000000 --- a/iterators/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "counting_iterator.hpp" -#include -#include - -int main(){ - std::vector v{1,3,37,1337,7}; - - for(auto x : counted(v)){ - std::cout << "v[" << x.index << "] = " << x.value << std::endl; - } - - for(auto x : counted(v)){ - x.value *= x.index; - } - - for(auto x : counted(v)){ - std::cout << "v[" << x.index << "] = " << x.value << std::endl; - } - - return 0; -} diff --git a/iterators/README.md b/ranges/README.md similarity index 60% rename from iterators/README.md rename to ranges/README.md index b6a2c8d..a4ec7cb 100644 --- a/iterators/README.md +++ b/ranges/README.md @@ -26,3 +26,18 @@ for(auto x : counted(v)) { ``` This will output the container `v`, with it's indeces. And it will multiply every value in `v` by 2. + +tuple element +============= + +```c++ +map<.., ..> m = {..}; +for(auto key : keys(m)) + ... key ... +for(auto v : values(m)) + ... v ... +``` + +Some helper functions for easy access to maps. It also works well on vectors of tuples, or any container with a tuple-like interface. +The general function is `nth_values(v)`, which allows you to iterate over the N-th element in the tuples of `v`. +For more information see tuple_element.h. Note that this does have a good const version, in contrast to the thing above (counted). \ No newline at end of file diff --git a/iterators/counting_iterator.hpp b/ranges/counting_iterator.hpp similarity index 100% rename from iterators/counting_iterator.hpp rename to ranges/counting_iterator.hpp diff --git a/ranges/main.cpp b/ranges/main.cpp new file mode 100644 index 0000000..6dec8ab --- /dev/null +++ b/ranges/main.cpp @@ -0,0 +1,50 @@ +#include +#include +#include + +#include "counting_iterator.hpp" +#include "tuple_element.hpp" + +void counting_iterator(){ + std::vector v{1,3,37,1337,7}; + + for(auto x : counted(v)){ + std::cout << "v[" << x.index << "] = " << x.value << std::endl; + } + + for(auto x : counted(v)){ + x.value *= x.index; + } + + for(auto x : counted(v)){ + std::cout << "v[" << x.index << "] = " << x.value << std::endl; + } +} + +void tuple_element (){ + std::map m1; + for(int i = -5; i <= 5; ++i) + m1[i] = i*i; + + for(auto & p : values(m1)){ + p -= 5; + } + + auto const & m = m1; + for(auto & p : values(m)){ // p is a const ref + std::cout << p << "\t"; + } + + std::cout << std::endl; + + for(auto & p : keys(m1)){ // p is a const ref, because keys in a map are const + std::cout << p << "\t"; + } + + std::cout << std::endl; +} + +int main(){ + counting_iterator(); + tuple_element(); +} diff --git a/ranges/tuple_element.hpp b/ranges/tuple_element.hpp new file mode 100644 index 0000000..621aa48 --- /dev/null +++ b/ranges/tuple_element.hpp @@ -0,0 +1,187 @@ +// +// 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); +} +