Skip to the content.

:heavy_check_mark: adaptor/queue_by_stack.hpp

Depends on

Required by

Verified with

Code

#pragma once


#include <concepts>
#include <utility>


#include "internal/dev_env.hpp"


namespace uni {


template<class In, class Out = In>
struct queue_by_stack {
    static_assert(std::same_as<typename In::value_type, typename Out::value_type>);
    static_assert(std::common_reference_with<typename In::size_type, typename Out::size_type>);

    using value_type = In::value_type;
    using size_type = std::common_type_t<typename In::size_type, typename Out::size_type>;

  protected:
    In _in;
    Out _out;

  private:
    inline void _shift() noexcept(NO_EXCEPT) {
        if(!this->_out.empty()) return;

        while(!this->_in.empty()) {
            this->_out.push(this->_in.top());
            this->_in.pop();
        }
    }

  public:
    queue_by_stack() noexcept = default;

    inline bool empty() const noexcept(NO_EXCEPT) {
        return this->_in.empty() && this->_out.empty();
    }

    inline auto size() const noexcept(NO_EXCEPT) {
        return this->_in.size() + this->_out.size();
    }


    inline decltype(auto) front() noexcept(NO_EXCEPT) {
        this->_shift();
        assert(!this->_out.empty());
        return this->_out.top();
    }

    template<std::convertible_to<value_type> T = value_type>
        requires std::is_move_constructible_v<T>
    inline decltype(auto) front_or(T&& val) const noexcept(NO_EXCEPT) {
        if(this->empty()) return static_cast<value_type>(std::forward<T>(val));
        else return this->front();
    }


    inline auto& clear() noexcept(NO_EXCEPT) {
        this->_in.clear(), this->_out.clear();
        return *this;
    }


    template<std::convertible_to<value_type> T = value_type>
    inline auto& push(T&& val) noexcept(NO_EXCEPT) {
        this->_in.push(std::forward<T>(val));
        return *this;
    }

    template<class... Args>
    inline decltype(auto) emplace(Args&&... args) noexcept(NO_EXCEPT) {
        return this->_in.emplace(std::forward<Args>(args)...);
    }


    auto& pop() noexcept(NO_EXCEPT) {
        this->_shift();
        assert(!this->_out.empty());

        this->_out.pop();
        return *this;
    }
};



} // namespace uni
#line 2 "adaptor/queue_by_stack.hpp"


#include <concepts>
#include <utility>


#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 9 "adaptor/queue_by_stack.hpp"


namespace uni {


template<class In, class Out = In>
struct queue_by_stack {
    static_assert(std::same_as<typename In::value_type, typename Out::value_type>);
    static_assert(std::common_reference_with<typename In::size_type, typename Out::size_type>);

    using value_type = In::value_type;
    using size_type = std::common_type_t<typename In::size_type, typename Out::size_type>;

  protected:
    In _in;
    Out _out;

  private:
    inline void _shift() noexcept(NO_EXCEPT) {
        if(!this->_out.empty()) return;

        while(!this->_in.empty()) {
            this->_out.push(this->_in.top());
            this->_in.pop();
        }
    }

  public:
    queue_by_stack() noexcept = default;

    inline bool empty() const noexcept(NO_EXCEPT) {
        return this->_in.empty() && this->_out.empty();
    }

    inline auto size() const noexcept(NO_EXCEPT) {
        return this->_in.size() + this->_out.size();
    }


    inline decltype(auto) front() noexcept(NO_EXCEPT) {
        this->_shift();
        assert(!this->_out.empty());
        return this->_out.top();
    }

    template<std::convertible_to<value_type> T = value_type>
        requires std::is_move_constructible_v<T>
    inline decltype(auto) front_or(T&& val) const noexcept(NO_EXCEPT) {
        if(this->empty()) return static_cast<value_type>(std::forward<T>(val));
        else return this->front();
    }


    inline auto& clear() noexcept(NO_EXCEPT) {
        this->_in.clear(), this->_out.clear();
        return *this;
    }


    template<std::convertible_to<value_type> T = value_type>
    inline auto& push(T&& val) noexcept(NO_EXCEPT) {
        this->_in.push(std::forward<T>(val));
        return *this;
    }

    template<class... Args>
    inline decltype(auto) emplace(Args&&... args) noexcept(NO_EXCEPT) {
        return this->_in.emplace(std::forward<Args>(args)...);
    }


    auto& pop() noexcept(NO_EXCEPT) {
        this->_shift();
        assert(!this->_out.empty());

        this->_out.pop();
        return *this;
    }
};



} // namespace uni
Back to top page