new ranges :D
This commit is contained in:
parent
d8592cd4f4
commit
9381a492f3
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;
|
||||
}
|
|
@ -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<N>(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).
|
50
ranges/main.cpp
Normal file
50
ranges/main.cpp
Normal file
|
@ -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();
|
||||
}
|
187
ranges/tuple_element.hpp
Normal file
187
ranges/tuple_element.hpp
Normal file
|
@ -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 a new issue