// Pila genérica sobre un arreglo de capacidad fija. Paso 5 del laboratorio.
#ifndef STACK_H
#define STACK_H

#include <cstddef>

#include "todo.h"

// Por ahora el arreglo se pide con new T[capacity], así que T debe tener un constructor
// sin argumentos, y se debe poder asignar. Stack<T> no compila con otros tipos.
//
// Invariantes:
//   1. size_ <= capacity_.
//   2. data_ == nullptr si y solo si capacity_ == 0.
//   3. Los elementos están en data_[0], ..., data_[size_ - 1]. El tope es data_[size_ - 1].
template <typename T>
class Stack {
public:
    explicit Stack(std::size_t) {
        todo("Stack::Stack");
    }
    ~Stack() {
        todo("Stack::~Stack");
    }

    // Las cuatro que faltan de la regla de cinco. Una pila desde la que se movió queda
    // vacía y con capacidad 0, y cumple los invariantes.

    void push(T) {  // Requiere !full().
        todo("Stack::push");
    }
    void pop() {  // Requiere !empty().
        todo("Stack::pop");
    }
    T& top() {  // Requiere !empty().
        todo("Stack::top");
    }
    const T& top() const {  // Requiere !empty().
        todo("Stack::top");
    }
    bool empty() const {
        todo("Stack::empty");
    }
    bool full() const {
        todo("Stack::full");
    }
    std::size_t size() const {
        todo("Stack::size");
    }
    std::size_t capacity() const {
        todo("Stack::capacity");
    }
    // Comprueba con assert los invariantes de arriba.
    void check_invariants() const {
        todo("Stack::check_invariants");
    }

private:
    T* data_ = nullptr;
    std::size_t capacity_ = 0;
    std::size_t size_ = 0;
};

#endif
