简体   繁体   中英

How to get a 'stack based' std::stack? (with fixed max size)

According to std::stack reference:

The type of the underlying container to use to store the elements. The container must satisfy the requirements of SequenceContainer. Additionally, it must provide the following functions with the usual semantics:

 back() push_back() pop_back()

The standard containers std::vector, std::deque and std::list satisfy these requirements. By default, if no container class is specified for a particular stack class instantiation, the standard container std::deque is used.

All of which are heap based containers.

The following actually compiles ( ):

std::stack<int, std::array<int, 12> > stack_of_months;

Until push is called.

Is there some trick to easily wrap the std::array to support those methodes so it may be used in the stack?

You should be able to use Boost's static_vector :

static_vector is a sequence container like with contiguous storage that can change in size, along with the static allocation , low overhead, and fixed capacity .

A working example:

std::stack<int, boost::container::static_vector<int, 4>> s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
// s.push(5); // would throw

@PaulMcKenzie And yes, it uses the stack as storage (if the object itself is stored in the stack, of course):

The number of elements in a static_vector may vary dynamically up to a fixed capacity because elements are stored within the object itself similarly to an array.

Live demo: https://wandbox.org/permlink/Gi40FrB0yX8dIwfA .

It wouldn't be too hard to wrap a std::array into something usable by std::stack , you just need to keep track of how many elements have been pushed and popped:

#include <array>
#include <stack>
#include <iostream>

template < typename T, size_t Size >
struct static_vector
{
  using value_type = T;
  using reference = T&;
  using const_reference = const T &;
  using size_type = size_t;

  static_vector()
    : size( 0 )
  {
  }

  std::array< T, Size > data;
  size_t size;

  void push_back( const_reference value )
  {
    data.at( size ) = value;
    size++;
  }

  void pop_back()
  {
    if ( size == 0 )
    {
      throw std::runtime_error( "empty" );
    }
    size--;
  }

  const_reference back() const
  {
    if ( size == 0 )
    {
      throw std::runtime_error( "empty" );
    }
    return data[ size - 1 ];
  }

  reference back()
  {
    if ( size == 0 )
    {
      throw std::runtime_error( "empty" );
    }
    return data[ size - 1 ];
  }
};

int main()
{
  std::stack< int, static_vector< int, 4 > > stack;
  stack.push( 1 );
  std::cout << stack.top() << "\n";
  stack.push( 2 );
  std::cout << stack.top() << "\n";
  stack.pop();
  std::cout << stack.top() << "\n";
  stack.pop();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM