Program Listing for File py2cpp.hpp

Return to documentation for file (py2cpp/py2cpp.hpp)

#pragma once

#include <initializer_list>
#include <range/v3/view/iota.hpp>
#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>
// 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;
        }
        constexpr auto operator++(int) -> _iterator
        {
            auto temp = *this;
            ++*this;
            return temp;
        }
    };

    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 static_cast<size_t>(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;
        }
    };

    if (stop < start) {
        stop = start;
    }
    return iterable_wrapper {start, stop};
}

// template <typename T>
// inline auto range(T start, T stop)
// {
//     using iota_return_type = decltype(ranges::views::iota(start, stop));

//     class iterable_wrapper : public iota_return_type
//     {
//       public:
//         using value_type [[maybe_unused]] = T; // luk:
//         using key_type [[maybe_unused]] = T;   // luk:

//         iterable_wrapper(iota_return_type&& base)
//             : iota_return_type{std::forward<iota_return_type>(base)}
//         {
//         }

//         [[nodiscard]] auto contains(T n) const -> bool
//         {
//             return !(n < *this->begin()) && n < *this->end();
//         }
//     };

//     return iterable_wrapper {ranges::views::iota(start, stop)};
// }

template <typename T>
inline 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 (const 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