Skip to the content.

:heavy_check_mark: adaptor/range_extractor.hpp

Depends on

Required by

Verified with

Code

#pragma once


#include <functional>
#include <optional>
#include <cassert>


#include "internal/dev_env.hpp"


namespace uni {


template<class Container>
struct range_extractor : Container {
    using size_type = typename Container::size_type;
    using value_type = typename Container::value_type;

  protected:
    using default_func_noarg_type = std::function<value_type(void)>;
    using default_func_type = std::function<value_type(size_type)>;

    size_type _begin = 0;
    size_type _end;

    int _default_type = 0;
    value_type _default_val = value_type();
    default_func_noarg_type _default_func_noarg;
    default_func_type _default_func;
    inline static value_type _tmp;

    inline value_type _get_default(const size_type key) const noexcept(NO_EXCEPT) {
        if(this->_default_type == 0) return this->_default_val;
        if(this->_default_type == 1) return this->_default_func_noarg();
        if(this->_default_type == 2) return this->_default_func(key);
        else assert(false);
    }

  public:
    template<class... Args>
    explicit range_extractor(Args&&... args) noexcept(NO_EXCEPT) : Container(std::forward<Args>(args)...) {
        this->_begin = 0;
        this->_end = this->size();
    }

    inline auto& extract(const size_type begin, const size_type end) noexcept(NO_EXCEPT) {
        assert(begin <= end);
        this->_begin = begin, this->_end = end;
        return *this;
    }


    inline auto& set_default(const value_type& val) noexcept(NO_EXCEPT) {
        this->_default_val = val;
        this->_default_type = 0;
        return *this;
    }

    inline auto& set_default(const default_func_noarg_type func) noexcept(NO_EXCEPT) {
        this->_default_func_noarg = func;
        this->_default_type = 1;
        return *this;
    }

    inline auto& set_default(const default_func_type func) noexcept(NO_EXCEPT) {
        this->_default_func = func;
        this->_default_type = 2;
        return *this;
    }


    inline auto& operator[](const size_type pos) noexcept(NO_EXCEPT) {
        if(pos < this->_begin or this->_end <= pos) return range_extractor::_tmp = this->_get_default(pos);
        return this->Container::operator[](pos);
    }

    inline const auto& operator[](const size_type pos) const noexcept(NO_EXCEPT) {
        if(pos < this->_begin or this->_end <= pos) return range_extractor::_tmp = this->_get_default(pos);
        return this->Container::operator[](pos);
    }

    inline auto& operator()(const size_type pos) noexcept(NO_EXCEPT) {
        return this->Container::operator[](pos);
    }

    inline const auto& operator()(const size_type pos) const noexcept(NO_EXCEPT) {
        return this->Container::operator[](pos);
    }

    inline std::optional<value_type> get(const size_type pos) const noexcept(NO_EXCEPT) {
        if(pos < this->_begin or this->_end <= pos) return {};
        return this->Container::operator[](pos);
    }
};


}
#line 2 "adaptor/range_extractor.hpp"


#include <functional>
#include <optional>
#include <cassert>


#line 2 "internal/dev_env.hpp"


#ifdef LOCAL_JUDGE
    inline constexpr bool DEV_ENV = true;
    inline constexpr bool NO_EXCEPT = false;
#else
    inline constexpr bool DEV_ENV = false;
    inline constexpr bool NO_EXCEPT = true;
#endif // LOCAL_JUDGE


#if __cplusplus >= 202100L
    #define CPP20 true
    #define CPP23 true
#elif __cplusplus >= 202002L
    #define CPP20 true
    #define CPP23 false
#else
    #define CPP20 false
    #define CPP23 false
#endif
#line 10 "adaptor/range_extractor.hpp"


namespace uni {


template<class Container>
struct range_extractor : Container {
    using size_type = typename Container::size_type;
    using value_type = typename Container::value_type;

  protected:
    using default_func_noarg_type = std::function<value_type(void)>;
    using default_func_type = std::function<value_type(size_type)>;

    size_type _begin = 0;
    size_type _end;

    int _default_type = 0;
    value_type _default_val = value_type();
    default_func_noarg_type _default_func_noarg;
    default_func_type _default_func;
    inline static value_type _tmp;

    inline value_type _get_default(const size_type key) const noexcept(NO_EXCEPT) {
        if(this->_default_type == 0) return this->_default_val;
        if(this->_default_type == 1) return this->_default_func_noarg();
        if(this->_default_type == 2) return this->_default_func(key);
        else assert(false);
    }

  public:
    template<class... Args>
    explicit range_extractor(Args&&... args) noexcept(NO_EXCEPT) : Container(std::forward<Args>(args)...) {
        this->_begin = 0;
        this->_end = this->size();
    }

    inline auto& extract(const size_type begin, const size_type end) noexcept(NO_EXCEPT) {
        assert(begin <= end);
        this->_begin = begin, this->_end = end;
        return *this;
    }


    inline auto& set_default(const value_type& val) noexcept(NO_EXCEPT) {
        this->_default_val = val;
        this->_default_type = 0;
        return *this;
    }

    inline auto& set_default(const default_func_noarg_type func) noexcept(NO_EXCEPT) {
        this->_default_func_noarg = func;
        this->_default_type = 1;
        return *this;
    }

    inline auto& set_default(const default_func_type func) noexcept(NO_EXCEPT) {
        this->_default_func = func;
        this->_default_type = 2;
        return *this;
    }


    inline auto& operator[](const size_type pos) noexcept(NO_EXCEPT) {
        if(pos < this->_begin or this->_end <= pos) return range_extractor::_tmp = this->_get_default(pos);
        return this->Container::operator[](pos);
    }

    inline const auto& operator[](const size_type pos) const noexcept(NO_EXCEPT) {
        if(pos < this->_begin or this->_end <= pos) return range_extractor::_tmp = this->_get_default(pos);
        return this->Container::operator[](pos);
    }

    inline auto& operator()(const size_type pos) noexcept(NO_EXCEPT) {
        return this->Container::operator[](pos);
    }

    inline const auto& operator()(const size_type pos) const noexcept(NO_EXCEPT) {
        return this->Container::operator[](pos);
    }

    inline std::optional<value_type> get(const size_type pos) const noexcept(NO_EXCEPT) {
        if(pos < this->_begin or this->_end <= pos) return {};
        return this->Container::operator[](pos);
    }
};


}
Back to top page