Joshua Moerman
13 years ago
5 changed files with 252 additions and 21 deletions
@ -1,21 +0,0 @@ |
|||||
#include "counting_iterator.hpp" |
|
||||
#include <vector> |
|
||||
#include <iostream> |
|
||||
|
|
||||
int main(){ |
|
||||
std::vector<int> 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; |
|
||||
} |
|
@ -0,0 +1,50 @@ |
|||||
|
#include <vector> |
||||
|
#include <map> |
||||
|
#include <iostream> |
||||
|
|
||||
|
#include "counting_iterator.hpp" |
||||
|
#include "tuple_element.hpp" |
||||
|
|
||||
|
void counting_iterator(){ |
||||
|
std::vector<int> 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<int, int> 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(); |
||||
|
} |
@ -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<string, int> 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<tuple<int, int, const int>> 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 <utility> |
||||
|
|
||||
|
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 <size_t N, typename Iterator> |
||||
|
struct tuple_iterator : public Iterator { |
||||
|
tuple_iterator(Iterator it) |
||||
|
: Iterator(it) |
||||
|
{} |
||||
|
|
||||
|
typename std::tuple_element<N, typename Iterator::value_type>::type & |
||||
|
operator*(){ |
||||
|
return std::get<N>(*(Iterator&)(*this)); |
||||
|
} |
||||
|
|
||||
|
typename std::tuple_element<N, typename Iterator::value_type>::type & |
||||
|
operator->(){ |
||||
|
return std::get<N>(*(Iterator&)(*this)); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template <size_t N, typename Iterator> |
||||
|
struct const_tuple_iterator : public Iterator { |
||||
|
const_tuple_iterator(Iterator it) |
||||
|
: Iterator(it) |
||||
|
{} |
||||
|
|
||||
|
typename std::tuple_element<N, typename Iterator::value_type>::type const & |
||||
|
operator*(){ |
||||
|
return std::get<N>(*(Iterator&)(*this)); |
||||
|
} |
||||
|
|
||||
|
typename std::tuple_element<N, typename Iterator::value_type>::type const & |
||||
|
operator->(){ |
||||
|
return std::get<N>(*(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 <size_t N, typename Container> |
||||
|
struct tuple_container_wrapper { |
||||
|
typedef tuple_iterator<N, typename Container::iterator> iterator; |
||||
|
typedef const_tuple_iterator<N, typename Container::const_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 <size_t N, typename Container> |
||||
|
struct const_tuple_container_wrapper { |
||||
|
typedef const_tuple_iterator<N, typename Container::const_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 <size_t N, typename Container> |
||||
|
details::tuple_container_wrapper<N, Container> |
||||
|
nth_values(Container & m) { |
||||
|
return details::tuple_container_wrapper<N, Container>(m); |
||||
|
} |
||||
|
|
||||
|
template <size_t N, typename Container> |
||||
|
details::const_tuple_container_wrapper<N, Container> |
||||
|
nth_values(Container const & m) { |
||||
|
return details::const_tuple_container_wrapper<N, Container>(m); |
||||
|
} |
||||
|
|
||||
|
// NOTE: keys in a map are always const, so a const-only function suffices
|
||||
|
template <typename Map> |
||||
|
details::const_tuple_container_wrapper<0, Map> |
||||
|
keys(Map const & m) { |
||||
|
return nth_values<0>(m); |
||||
|
} |
||||
|
|
||||
|
template <typename Map> |
||||
|
details::tuple_container_wrapper<1, Map> |
||||
|
values(Map & m) { |
||||
|
return nth_values<1>(m); |
||||
|
} |
||||
|
|
||||
|
template <typename Map> |
||||
|
details::const_tuple_container_wrapper<1, Map> |
||||
|
values(Map const & m) { |
||||
|
return nth_values<1>(m); |
||||
|
} |
||||
|
|
Reference in new issue