A primer::lua_ref_seq is a dynamically-sized sequence
of lua_ref objects.
The intended usage is to allow handling lua functions with multiple return
values. Given a stack full of return values, they can all be popped at
once into a lua_ref_seq
using a call to pop_stack
or pop_n.
inline lua_ref_seq pop_n(lua_State * L, int n);
inline lua_ref_seq pop_stack(lua_State * L);
Pop |
|
Pop the entire stack. Throws |
They can be restored in the same order using lua_ref_seq
member function push_each.
Because a lua_ref_seq represents
multiple values and not just one, it can't be used with primer::push.
(primer::push is required
to push exactly one item.)
However, lua_ref_seq is
essentially just a std::vector<lua_ref>, as you'll see from it's synopsis.
To prevent it from being used accidentally as a std::vector<lua_ref> with push
or read, which could cause
bugs, it is implemented as a struct
containing a std::vector<lua_ref>
member, which forwards most of the member functions of std::vector.
Instead of lua_ref_seq
you could simply use std::vector<lua_ref> and push and read that instead. But
when you push it for instance, it's going to push a single table which
contains the sequence of values, due to the semantics we give to std::vector (see the
containers section), which is different from simply pushing all
of those values onto the stack.
struct lua_ref_seq { using refs_t = std::vector<lua_ref>; refs_t refs_;bool push_each(lua_State * L) const noexcept { bool result = true; for (const auto & r : refs_) { bool temp = r.push(L); result = result && temp; } return result; } // // Forward MANY methods from std::vector... // std::size_t size() const { return refs_.size(); } using value_type = refs_t::value_type; using reference = refs_t::reference; using const_reference = refs_t::const_reference; // Index reference operator[](std::size_t i) { return refs_[i]; } const_reference operator[](std::size_t i) const { return refs_[i]; } reference at(std::size_t i) { return refs_.at(i); } const_reference at(std::size_t i) const { return refs_.at(i); } reference front() { return refs_.front(); } const_reference front() const { return refs_.front(); } reference back() { return refs_.back(); } const_reference back() const { return refs_.back(); } // Support iteration using iterator = refs_t::iterator; using const_iterator = refs_t::const_iterator; iterator begin() { return refs_.begin(); } const_iterator begin() const { return refs_.begin(); } iterator end() { return refs_.end(); } const_iterator end() const { return refs_.end(); } // Manipulation void reserve(std::size_t s) { refs_.reserve(s); } void clear() { refs_.clear(); } void resize(std::size_t s) { refs_.resize(s); } void pop_back() { refs_.pop_back(); } template <typename... Args> void emplace_back(Args &&... args) { refs_.emplace_back(std::forward<Args>(args)...); } template <typename... Args> void emplace(const_iterator pos, Args &&... args) { refs_.emplace(pos, std::forward<Args>(args)...); } template <typename InputIt> iterator insert(const_iterator pos, InputIt first, InputIt last) { return refs_.insert(pos, first, last); } };
Push all the refs onto the stack in succession. Return of |