Program Listing for File py2cpp.hpp¶
↰ Return to documentation for file (py2cpp/py2cpp.hpp)
#pragma once
#include <algorithm> // std::max
#include <initializer_list>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
template <typename T> using Value_type = typename T::value_type;
namespace py {
template <typename T, typename TIter = decltype(std::begin(std::declval<T>())),
typename = decltype(std::end(std::declval<T>()))>
constexpr auto enumerate(T &&iterable) {
struct iterator {
size_t i;
TIter iter;
auto operator!=(const iterator &other) const -> bool {
return iter != other.iter;
}
void operator++() {
++i;
++iter;
}
auto operator*() const { return std::tie(i, *iter); }
auto operator*() { return std::tie(i, *iter); }
};
struct iterable_wrapper {
T iterable;
auto begin() { return iterator{0, std::begin(iterable)}; }
auto end() { return iterator{0, std::end(iterable)}; }
};
return iterable_wrapper{std::forward<T>(iterable)};
}
// template <typename T>
// constexpr auto range(T stop) {
// struct iterator {
// T i;
// constexpr bool operator!=(const iterator &other) const { return i !=
// other.i; } constexpr bool operator==(const iterator &other) const {
// return i == other.i; } constexpr T operator*() const { return i; }
// constexpr iterator &operator++() {
// ++i;
// return *this;
// }
// };
// struct iterable_wrapper {
// using value_type = T; // luk
// T stop;
// constexpr auto begin() const { return iterator{0}; }
// constexpr auto end() const { return iterator{stop}; }
// constexpr auto empty() const -> bool { return stop == 0; }
// constexpr auto size() const -> size_t { return stop; }
// constexpr auto operator[](size_t n) const -> T { return n; } // no
// bounds checking constexpr auto contains(T n) const -> bool { return n
// < stop; }
// };
// if (stop < 0) stop = 0;
// return iterable_wrapper{stop};
// }
template <typename T> inline constexpr auto range(T start, T stop) {
struct _iterator {
T i;
constexpr auto operator!=(const _iterator &other) const -> bool {
return this->i != other.i;
}
constexpr auto operator==(const _iterator &other) const -> bool {
return this->i == other.i;
}
constexpr auto operator*() const -> T { return this->i; }
constexpr auto operator++() -> _iterator & {
++this->i;
return *this;
}
};
struct iterable_wrapper {
public:
using value_type [[maybe_unused]] = T; // luk:
using key_type [[maybe_unused]] = T; // luk:
using iterator = _iterator; // luk
T start;
T stop;
[[nodiscard]] constexpr auto begin() const {
return iterator{this->start};
}
[[nodiscard]] constexpr auto end() const {
return iterator{this->stop};
}
[[nodiscard]] constexpr auto empty() const -> bool {
return this->stop == this->start;
}
[[nodiscard]] constexpr auto size() const -> size_t {
return this->stop - this->start;
}
constexpr auto operator[](size_t n) const -> T {
return T(this->start + n);
} // no bounds checking
[[nodiscard]] constexpr auto contains(T n) const -> bool {
return !(n < this->start) && n < this->stop;
}
};
stop = std::max(stop, start);
// if (stop < start) {
// stop = start;
// }
return iterable_wrapper{start, stop};
}
template <typename T> inline constexpr auto range(T stop) {
return range(T(0), stop);
}
template <typename Key> class set : public std::unordered_set<Key> {
using Self = set<Key>;
public:
set() : std::unordered_set<Key>{} {}
template <typename FwdIter>
set(const FwdIter &start, const FwdIter &stop)
: std::unordered_set<Key>(start, stop) {}
set(std::initializer_list<Key> init) : std::unordered_set<Key>{init} {}
auto contains(const Key &key) const -> bool {
return this->find(key) != this->end();
}
auto copy() const -> set { return *this; }
auto operator=(const set &) -> set & = delete;
auto operator=(set &&) noexcept -> set & = default;
set(set<Key> &&) noexcept = default;
// private:
set(const set<Key> &) = default;
};
template <typename Key>
inline auto operator<(const Key &key, const set<Key> &m) -> bool {
return m.contains(key);
}
template <typename Key> inline auto len(const set<Key> &m) -> size_t {
return m.size();
}
// template <typename Key>
// set(std::initializer_list<Key>) -> set<Key>;
// template <typename Key>
// set(std::initializer_list<const char*> ) -> set<std::string>;
template <typename Iter> struct key_iterator : Iter {
explicit key_iterator(Iter it) : Iter(it) {}
auto operator*() const { return Iter::operator*().first; }
auto operator++() -> key_iterator & {
Iter::operator++();
return *this;
}
};
template <typename Key, typename T>
class dict : public std::unordered_map<Key, T> {
using Self = dict<Key, T>;
using Base = std::unordered_map<Key, T>;
public:
using value_type = std::pair<const Key, T>;
dict() : std::unordered_map<Key, T>{} {}
dict(std::initializer_list<value_type> init)
: std::unordered_map<Key, T>{init} {}
// template <class Sequence>
// explicit dict(const Sequence &S) {
// this->reserve(S.size());
// for (auto&& [i_v, v] : py::enumerate(S)) {
// (*this)[v] = i_v;
// }
// }
auto contains(const Key &key) const -> bool {
return this->find(key) != this->end();
}
auto get(const Key &key, const T &default_value) -> T {
if (!contains(key)) {
return default_value;
}
return (*this)[key];
}
auto begin() const {
using Iter = decltype(std::unordered_map<Key, T>::begin());
return key_iterator<Iter>{std::unordered_map<Key, T>::begin()};
}
auto end() const {
using Iter = decltype(std::unordered_map<Key, T>::end());
return key_iterator<Iter>{std::unordered_map<Key, T>::end()};
}
auto items() -> std::unordered_map<Key, T> & { return *this; }
auto items() const -> const std::unordered_map<Key, T> & { return *this; }
auto copy() const -> Self { return *this; }
auto operator[](const Key &k) const -> const T & {
return this->at(k); // luk: a bug in std::unordered_map?
}
auto operator[](const Key &k) -> T & { return Base::operator[](k); }
auto operator=(const Self &) -> Self & = delete;
auto operator=(Self &&) noexcept -> dict & = default;
dict(dict<Key, T> &&) noexcept = default;
~dict() = default;
// private:
dict(const dict<Key, T> &) = default;
};
template <typename Key, typename T>
inline auto operator<(const Key &key, const dict<Key, T> &m) -> bool {
return m.contains(key);
}
template <typename Key, typename T>
inline auto len(const dict<Key, T> &m) -> size_t {
return m.size();
}
// template <typename Key, typename T>
// dict(std::initializer_list<std::pair<const Key, T>>) -> dict<Key, T>;
// template <class Sequence>
// dict(const Sequence& S)
// -> dict<std::remove_cv_t<decltype(*std::begin(S))>, size_t>;
} // namespace py