You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
4.6 KiB
188 lines
4.6 KiB
12 years ago
|
//
|
||
|
// 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);
|
||
|
}
|
||
|
|