Offtopically, I wrote a few "useful" utility functions for C++ in an effort to make it more pythonic.
(I'm aware that this is probably the C++ equivalent of "I made a poopy mommy~!" But I thought someone might find it useful).
The first one is zip. It returns a container of tuples, the only limitation is that the container of the passed in objects should be the same.
For clarification, if you run:
Language: cpp
std::deque<std::string> a;
std::deque<int> b;
std::deque<std::multimap> c;
std::deque<std::pair<int, std::string>> d;
for (auto i : zip(a, b, c, d)) {
}
You'll be iterating over a std::tuple<std::string, int, std::multimap, std::pair<int, std::string>> with the elements paired up in the manner that you'd expect.
Unlike the boost::zip, this does not require that the lists be the same size, it functions like python zip in that it's automatically truncated to the shortest length.
Language: cpp
template <class ContainerA>
unsigned commonLength(unsigned len, const ContainerA &first) {
unsigned firstLen = first.size();
if (len > firstLen) {
len = firstLen;
}
return len;
}
template <class ContainerA, class... Containers>
unsigned commonLength(unsigned len, const ContainerA &first, const Containers&... rest) {
unsigned firstLen = first.size();
if (len > firstLen) {
len = firstLen;
}
return commonLength(len, rest...);
}
template <template <typename...> class Container, typename TypeA>
std::tuple<TypeA> getTupleFrom(unsigned index, Container<TypeA> const& first) {
return std::tuple<TypeA>(first[index]);
}
template <template <typename...> class Container, typename TypeA, typename... Types>
std::tuple<TypeA, Types...> getTupleFrom(unsigned index, Container<TypeA> const& first, Container<Types> const&... rest) {
return std::tuple_cat(std::tuple<TypeA>(first[index]), getTupleFrom<Container, Types...>(index, rest...));
}
template <template <typename...> class Container, typename... Types>
Container<std::tuple<Types...>> zip(Container<Types> const&... args) {
unsigned len = commonLength(std::numeric_limits<unsigned>::max(), args...);
Container<std::tuple<Types...>> res;
std::tuple<Types...> item;
for (unsigned i=0; i<len; i++) {
item = getTupleFrom<Container, Types...>(i, args...);
res.push_back(item);
}
return res;
}
Next is a wrapper, to make reverse walking of a container through a range based for easy/possible.
Language: cpp
for (auto i : reverseIterate(mylist)) {
}
Language: cpp
template <typename Iterable>
struct ReverseWrapper {
private:
Iterable& m_iterable;
public:
ReverseWrapper(Iterable& iterable) : m_iterable(iterable) {}
auto begin() const ->decltype(m_iterable.rbegin()) {
return m_iterable.rbegin();
}
auto end() const ->decltype(m_iterable.rend()) {
return m_iterable.rend();
}
};
template <typename Iterable>
ReverseWrapper<Iterable> reverseIterate(Iterable& list) {
return ReverseWrapper<Iterable>(list);
}
Finally, range. It works like python's range statement in that it returns a list or other container for the given range. I haven't bothered to make a functor based version (like an xrange generator) yet. This is because my zip function doesn't work with that concept yet. If I ever need it I'll write it and put it here.
Language: cpp
template <template <typename...> class Container, typename Numeric>
Container<Numeric> range(Numeric min, Numeric max, Numeric diff) {
Container<Numeric> res;
while ((diff > 0 && max > min) ||
(diff < 0 && min > max)) {
res.push_back(min);
min += diff;
}
return res;
}
template <template <typename...> class Container, typename Numeric>
Container<Numeric> range(Numeric max) {
Container<Numeric> res;
int min = 0;
while (max > min) {
res.push_back(min);
min += 1;
}
return res;
}
template <template <typename...> class Container, typename Numeric>
Container<Numeric> range(Numeric min, Numeric max) {
Container<Numeric> res;
while (max > min) {
res.push_back(min);
min += 1;
}
return res;
}