// bslstl_stack.h                                                     -*-C++-*-
#ifndef INCLUDED_BSLSTL_STACK
#define INCLUDED_BSLSTL_STACK

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide an STL-compliant stack class.
//
//@CLASSES:
//   bsl::stack: STL-compliant stack template
//
//@CANONICAL_HEADER: bsl_stack.h
//
//@SEE_ALSO: bslstl_deque, bslstl_vector, bslstl_list, bslstl_queue,
//           bslstl_priorityqueue
//
//@DESCRIPTION: This component defines a single class template, 'bsl::stack',
// a container adapter that takes an underlying container and provides a stack
// interface which the user accesses primarily through 'push', 'pop', and 'top'
// operations.  A 'deque' (the default), 'vector', or 'list' may be used, but
// any container which supports 'push_back', 'pop_back', 'back', and 'size',
// plus a template specialization 'uses_allocator::type', may be used.
//
// A stack meets the requirements of a container adaptor as described in the
// C++ standard [stack].  The 'stack' implemented here adheres to the C++11
// standard when compiled with a C++11 compiler, and makes the best
// approximation when compiled with a C++03 compiler.  In particular, for C++03
// we emulate move semantics, but limit forwarding (in 'emplace') to 'const'
// lvalues, and make no effort to emulate 'noexcept' or initializer-lists.
//
///Requirements on 'CONTAINER'
///---------------------------
// The 'bsl::stack' adapter can accept for its (optional) 'CONTAINER' template
// parameter 'bsl::deque' (the default), 'bsl::vector', 'bsl::list', or other
// container classes that support the following types and methods.
//
///Required Types
/// - - - - - - -
//: o 'value_type'
//: o 'reference'
//: o 'const_reference'
//: o 'size_type'
//: o 'allocator_type' (if any 'stack' constructor taking an allocator is used)
//
///Required Methods, Free Operators, and Free Functions
/// - - - - - - - - - - - - - - - - - - - - - - - - - -
//: o 'void push_back(const value_type&)' (and variant taking rvalue reference)
//: o 'void pop_back()'
//: o 'reference back()'
//: o 'size_type size() const'
//: o 'const_reference back() const'
//: o 'emplace_back'
//: o copy-assignment and move-assignment operators
//: o free '==', '!=', '<', '>', '<=', '>=' operators
//: o free 'swap' function (found via ADL with 'std::swap' in the lookup set)
//
///Requirements on 'VALUE'
///-----------------------
// The following term is used to more precisely specify the requirements on
// template parameter types in function-level documentation:
//
//: *equality-comparable*:
//:   The type provides an equality-comparison operator that defines an
//:   equivalence relationship and is both reflexive and transitive.
//
///'VALUE' and 'CONTAINER::value_type'
///- - - - - - - - - - - - - - - - - -
// When the 'CONTAINER' template parameter is omitted the 'VALUE' template
// parameter specifies the 'value_type' of 'bsl::vector', the default container
// type.  The 'VALUE' template has no other role.
//
// For C++17 and later, the behavior is undefined unless:
//..
//  true == bsl::is_same<VALUE, typename CONTAINER::value_type>::value
//..
// Prior to C++17, 'CONTAINER::value_type' determines the contained value type
// and 'VALUE' is simply ignored.  The resulting code may work with instances
// of 'VALUE' (e.g., 'VALUE' is convertible to 'CONTAINER::value_type') or not
// (compiler errors).
//
///Memory Allocation
///-----------------
// No memory allocator template arg is directly supplied to this class, the
// allocator type used is the allocator specified for the container class.
// Some functions of this template only exist if type
// 'CONTAINER::allocator_type' exists, and if it does exist it is assumed to be
// the allocator type used by 'CONTAINER', and that 'CONTAINER' supports
// constructors of this type.
//
///'bslma'-Style Allocators
///------------------------
// The constructors of this class take, as optional parameters, allocators of
// the object's parameterized 'CONTAINER::allocator_type' type, and allocators
// of this type are propagated to all constructors of the underlying container.
// In the case of container types 'bsl::deque' (the default type),
// 'bsl::vector', and 'bsl::list', 'CONTAINER::allocator_type' is
// 'bsl::allocator' which is implicitly convertible from 'bslma::Allocator *',
// and which can be converted to a 'bslma::Allocator *' through the 'mechanism'
// accessor.
//
// Hence if the underlying container takes 'bsl::allocator', then the 'stack'
// object can take 'bslma_Allocator *'s to supply memory allocation.  If no
// allocator is specified, 'allocator()' is used, which winds up using
// 'bslma::Default::allocator(0)'.
//
///Operations
///----------
// Below is a list of public methods of the 'bsl::stack' class that effectively
// forward their implementations to corresponding operations in the held
// container (referenced as 'c') which is here assumed to be either
// 'bsl::deque', or 'bsl::vector', or 'bsl::list'.
//..
//  Legend
//  ------
//  'C'             - (template parameter) type 'CONTAINER' of the stack
//  'V'             - (template parameter) type 'VALUE'     of the stack
//  's', 't'        - two distinct objects of type 'stack<V, C>'
//
//  'nc'            - number of elements in container 'c'
//  'n', 'm'        - number of elements in 's' and 't', respectively
//  'al'            - STL-style memory allocator
//  'v'             - an object of type 'V'
//
//  +----------------------------------------------------+--------------------+
//  | Note: the following estimations of operation complexity assume the      |
//  | underlying container is a 'bsl::deque', 'bsl::vector', or 'bsl::list'.  |
//  +----------------------------------------------------+--------------------+
//  | Operation                                          | Complexity         |
//  +====================================================+====================+
//  | stack<V, C> s;    (default construction)           | O(1)               |
//  | stack<V, C> s(al);                                 |                    |
//  +----------------------------------------------------+--------------------+
//  | stack<V, C> s(c);                                  | O(nc)              |
//  | stack<V, C> s(c, al);                              |                    |
//  +----------------------------------------------------+--------------------+
//  | stack<V, C> s(t);                                  | O(n)               |
//  | stack<V, C> s(t, al);                              |                    |
//  +----------------------------------------------------+--------------------+
//  | s.~stack(V, C>(); (destruction)                    | O(n)               |
//  +----------------------------------------------------+--------------------+
//  | s = t;          (assignment)                       | O(n)               |
//  +----------------------------------------------------+--------------------+
//  | s.push(v)                                          | O(1)               |
//  +----------------------------------------------------+--------------------+
//  | s.pop()                                            | O(1)               |
//  +----------------------------------------------------+--------------------+
//  | s.top()                                            | O(1)               |
//  +----------------------------------------------------+--------------------+
//  | s == t, s != t                                     | O(n)               |
//  +---------------------------------------------------+--------------------+
//  | s < t, s <= t, s > t, s >= t                       | O(n)               |
//  +----------------------------------------------------+--------------------+
//  | s.swap(t), swap(s,t)                               | depends on the     |
//  |                                                    | container; for     |
//  |                                                    | deque, vector, and |
//  |                                                    | list:              |
//  |                                                    | O(1) if 's' and    |
//  |                                                    | 't' use the same   |
//  |                                                    | allocator,         |
//  |                                                    | O(n + m) otherwise |
//  +----------------------------------------------------+--------------------+
//  | s.size()                                           | O(1) if 'C' is     |
//  |                                                    | deque or vector    |
//  +----------------------------------------------------+--------------------+
//  | s.empty()                                          | O(1)               |
//  +----------------------------------------------------+--------------------+
//..
//
///Usage
///-----
// In this section we show intended use of this component.
//
///Example 1: Household Chores To Do List
/// - - - - - - - - - - - - - - - - - - -
// Suppose a husband wants to keep track of chores his wife has asked him to
// do.  Over the years of being married, he has noticed that his wife generally
// wants the most recently requested task done first.  If she has a new task in
// mind that is low-priority, she will avoid asking for it until higher
// priority tasks are finished.  When he has finished all tasks, he is to
// report to his wife that he is ready for more.
//
// First, we define the class implementing the to-do list.
//..
//  class ToDoList {
//      // DATA
//      bsl::stack<const char *> d_stack;
//
//    public:
//      // MANIPULATORS
//      void enqueueTask(const char *task);
//          // Add the specified 'task', a string describing a task, to the
//          // list.  Note the lifetime of the string referred to by 'task'
//          // must exceed the lifetime of the task in this list.
//
//      bool finishTask();
//          // Remove the current task from the list.  Return 'true' if a task
//          // was removed and it was the last task on the list, and return
//          // 'false' otherwise.
//
//      // ACCESSORS
//      const char *currentTask() const;
//          // Return the string representing the current task.  If there
//          // is no current task, return the string "<EMPTY>", which is
//          // not a valid task.
//  };
//
//  // MANIPULATORS
//  void ToDoList::enqueueTask(const char *task)
//  {
//      d_stack.push(task);
//  }
//
//  bool ToDoList::finishTask()
//  {
//      if (!d_stack.empty()) {
//          d_stack.pop();
//
//          return d_stack.empty();
//      }
//
//      return false;
//  };
//
//  // ACCESSORS
//  const char *ToDoList::currentTask() const
//  {
//      if (d_stack.empty()) {
//          return "<EMPTY>";
//      }
//
//      return d_stack.top();
//  }
//..
// Then, create an object of type 'ToDoList'.
//..
//  ToDoList toDoList;
//..
// Next, a few tasks are requested:
//..
//  toDoList.enqueueTask("Change the car's oil.");
//  toDoList.enqueueTask("Pay the bills.");
//..
// Then, the husband watches the Yankee's game on TV.  Upon returning to the
// list he consults the list to see what task is up next:
//..
//  assert(!strcmp("Pay the bills.", toDoList.currentTask()));
//..
// Next, he sees that he has to pay the bills.  When the bills are finished, he
// flushes that task from the list:
//..
//  assert(false == toDoList.finishTask());
//..
// Then, he consults the list for the next task.
//..
//  assert(!strcmp("Change the car's oil.", toDoList.currentTask()));
//..
// Next, he sees he has to change the car's oil.  Before he can get started,
// another request comes:
//..
//  toDoList.enqueueTask("Get some hot dogs.");
//  assert(!strcmp("Get some hot dogs.", toDoList.currentTask()));
//..
// Then, he drives the car to the convenience store and picks up some hot dogs
// and buns.  Upon returning home, he gives the hot dogs to his wife, updates
// the list, and consults it for the next task.
//..
//  assert(false == toDoList.finishTask());
//  assert(!strcmp("Change the car's oil.", toDoList.currentTask()));
//..
// Next, he finishes the oil change, updates the list, and consults it for the
// next task.
//..
//  assert(true == toDoList.finishTask());
//  assert(!strcmp("<EMPTY>", toDoList.currentTask()));
//..
// Finally, the wife has now been informed that everything is done, and she
// makes another request:
//..
//  toDoList.enqueueTask("Clean the rain gutters.");
//..

#include <bslscm_version.h>

#include <bslstl_deque.h>

#include <bslalg_swaputil.h>

#include <bslma_usesbslmaallocator.h>
#include <bslma_isstdallocator.h>

#include <bslmf_assert.h>
#include <bslmf_enableif.h>
#include <bslmf_isconvertible.h>
#include <bslmf_issame.h>
#include <bslmf_movableref.h>
#include <bslmf_nestedtraitdeclaration.h>
#include <bslmf_usesallocator.h>
#include <bslmf_util.h>    // 'forward(V)'

#include <bsls_compilerfeatures.h>
#include <bsls_keyword.h>
#include <bsls_libraryfeatures.h>
#include <bsls_platform.h>
#include <bsls_util.h>     // 'forward<T>(V)'

#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
// Include version that can be compiled with C++03
// Generated on Thu Oct 21 10:11:37 2021
// Command line: sim_cpp11_features.pl bslstl_stack.h
# define COMPILING_BSLSTL_STACK_H
# include <bslstl_stack_cpp03.h>
# undef COMPILING_BSLSTL_STACK_H
#else

namespace bsl {

                             // ===========
                             // class stack
                             // ===========

template <class VALUE, class CONTAINER = deque<VALUE> >
class stack {
    // This 'class' defines a container adapter which supports access primarily
    // via 'push', 'pop', and 'top'.  This type can be based on a variety of
    // other container types, including 'deque', 'vector', and 'list'.  This
    // type is value-semantic if the supporting 'CONTAINER' and 'VALUE' are
    // value-semantic.
    //
    // Note that we never use 'VALUE' in the implementation except in the
    // default argument of 'CONTAINER'.  We use 'CONTAINER::value_type' for
    // everything, which means that if 'CONTAINER' is specified, then 'VALUE'
    // is ignored.

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY
    // STATIC CHECK: Type mismatch is UB per C++17
    BSLMF_ASSERT((is_same<VALUE, typename CONTAINER::value_type>::value));
#endif

  private:
    // PRIVATE TYPES
    typedef BloombergLP::bslmf::MovableRefUtil  MoveUtil;
        // This 'typedef' is a convenient alias for the utility associated with
        // movable references.

  public:
    // PUBLIC TYPES
    typedef typename CONTAINER::value_type      value_type;
    typedef typename CONTAINER::reference       reference;
    typedef typename CONTAINER::const_reference const_reference;
    typedef typename CONTAINER::size_type       size_type;
    typedef          CONTAINER                  container_type;


  protected:
    // PROTECTED DATA
    container_type  c;    // We are required by the standard to have the
                          // container be a protected variable named 'c'.

  private:
    // FRIENDS
    template <class VAL, class CONT>
    friend bool operator==(const stack<VAL, CONT>&, const stack<VAL, CONT>&);
    template <class VAL, class CONT>
    friend bool operator!=(const stack<VAL, CONT>&, const stack<VAL, CONT>&);
    template <class VAL, class CONT>
    friend bool operator< (const stack<VAL, CONT>&, const stack<VAL, CONT>&);
    template <class VAL, class CONT>
    friend bool operator> (const stack<VAL, CONT>&, const stack<VAL, CONT>&);
    template <class VAL, class CONT>
    friend bool operator<=(const stack<VAL, CONT>&, const stack<VAL, CONT>&);
    template <class VAL, class CONT>
    friend bool operator>=(const stack<VAL, CONT>&, const stack<VAL, CONT>&);

  public:
    // TRAITS
    BSLMF_NESTED_TRAIT_DECLARATION_IF(
        stack,
        BloombergLP::bslma::UsesBslmaAllocator,
        BloombergLP::bslma::UsesBslmaAllocator<container_type>::value);

    // CREATORS
    explicit stack();
        // Create an empty stack.  No allocator will be provided to the
        // underlying container.  That container's memory allocation will be
        // provided by the default allocator of its type.

    stack(const stack& original);
        // Create a stack having the value of the specified 'original'.  The
        // currently installed default allocator is used to supply memory.

    stack(BloombergLP::bslmf::MovableRef<stack> original);
        // Create a stack having the value of the specified 'original' by
        // moving the contents of 'original' to the new stack.  The allocator
        // associated with 'original' is propagated for use in the new stack.
        // 'original' is left in a valid but unspecified state.

    explicit
    stack(const CONTAINER& container);
        // Create a stack whose underlying container has the value of the
        // specified 'container'.  The currently installed default allocator is
        // used to supply memory.

    explicit
    stack(BloombergLP::bslmf::MovableRef<CONTAINER> container);
        // Create a stack whose underlying container has the value of the
        // specified 'container' (on entry) by moving the contents of
        // 'container' to the new stack.  The allocator associated with
        // 'container' is propagated for use in the new stack.  'container' is
        // left in a valid but unspecified state.

    template <class ALLOCATOR>
    explicit
    stack(const ALLOCATOR& basicAllocator,
          typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                             ALLOCATOR>::type * = 0);
        // Create an empty stack, and use the specified 'basicAllocator' to
        // supply memory.  If 'CONTAINER::allocator_type' does not exist, this
        // constructor may not be used.

    template <class ALLOCATOR>
    stack(const CONTAINER& container,
          const ALLOCATOR& basicAllocator,
          typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                             ALLOCATOR>::type * = 0);
        // Create a stack whose underlying container has the value of the
        // specified 'container', and use the specified 'basicAllocator' to
        // supply memory.  If 'CONTAINER::allocator_type' does not exist, this
        // constructor may not be used.

    template <class ALLOCATOR>
    stack(const stack&     original,
          const ALLOCATOR& basicAllocator,
          typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                             ALLOCATOR>::type * = 0);
        // Create a stack having the value of the specified stack 'original'
        // and use the specified 'basicAllocator' to supply memory.  If
        // 'CONTAINER::allocator_type' does not exist, this constructor may not
        // be used.

    template <class ALLOCATOR>
    stack(BloombergLP::bslmf::MovableRef<CONTAINER> container,
          const ALLOCATOR&                          basicAllocator,
          typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                             ALLOCATOR>::type * = 0);
        // Create a stack whose underlying container has the value of the
        // specified 'container' (on entry) that uses 'basicAllocator' to
        // supply memory by using the allocator-extended move constructor of
        // 'CONTAINER.  'container' is left in a valid but unspecified state.
        // A 'bslma::Allocator *' can be supplied for 'basicAllocator' if the
        // (template parameter) 'ALLOCATOR' is 'bsl::allocator' (the default).
        // This method assumes that 'CONTAINER' has a move constructor.  If
        // 'CONTAINER::allocator_type' does not exist, this constructor may not
        // be used.

    template <class ALLOCATOR>
    stack(BloombergLP::bslmf::MovableRef<stack> original,
          const ALLOCATOR&                      basicAllocator,
          typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                             ALLOCATOR>::type * = 0);
        // Create a stack having the value of the specified 'original' (on
        // entry) that uses 'basicAllocator' to supply memory by using the
        // allocator-extended moved constructor of 'CONTAINER'.  'original' is
        // left in a valid but unspecified state.  Note that a
        // 'bslma::Allocator *' can be supplied for 'basicAllocator' if the
        // (template parameter) 'ALLOCATOR' is 'bsl::allocator' (the default).
        // Also note that this method assumes that 'CONTAINER' has a move
        // constructor.  Also note that if 'CONTAINER::allocator_type' does not
        // exist, this constructor may not be used.

    // MANIPULATORS
    stack& operator=(const stack& rhs);
        // Assign to this object the value of the specified 'rhs' object, and
        // return a reference providing modifiable access to this object.

    stack& operator=(BloombergLP::bslmf::MovableRef<stack> rhs)
                                    BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(false);
        // Assign to this object the value of the specified 'rhs' object, and
        // return a reference providing modifiable access to this object.  The
        // contents of 'rhs' are moved to this stack using the move-assignment
        // operator of 'CONTAINER'.  'rhs' is left in a valid but unspecified
        // state, and if an exception is thrown, '*this' is left in a valid but
        // unspecified state.

#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
    template <class... Args>
    reference emplace(Args&&... args);
        // Push onto this stack a newly created 'value_type' object constructed
        // by forwarding 'get_allocator()' (if required) and the specified
        // (variable number of) 'args' to the corresponding constructor of
        // 'value_type'.  Return a reference providing modifiable access to the
        // inserted element.

#endif

    void pop();
        // Remove the top element from this stack.  The behavior is undefined
        // if this stack is empty.

    void push(const value_type& value);
        // Push the specified 'value' onto the top of this stack.

    void push(BloombergLP::bslmf::MovableRef<value_type> value);
        // Push onto this stack a 'value_type' object having the value of the
        // specified 'value' (on entry) by moving the contents of 'value' to
        // the new object on this stack.  'value' is left in a valid but
        // unspecified state.

    void swap(stack& other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(
                                  bsl::is_nothrow_swappable<CONTAINER>::value);
        // Exchange the value of this stack with the value of the specified
        // 'other' stack.

    reference top();
        // Return a reference to the element at the top of this stack.  The
        // behavior is undefined if this stack is empty.

    // ACCESSORS
    bool empty() const;
        // Return 'true' if this stack contains no elements and 'false'
        // otherwise.

    size_type size() const;
        // Return the number of elements contained in this stack.

    const_reference top() const;
        // Return a reference providing non-modifiable access to the element at
        // the top of this stack.  The behavior is undefined if the stack is
        // empty.
};

#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
// CLASS TEMPLATE DEDUCTION GUIDES

template<class CONTAINER,
         class = bsl::enable_if_t<!bsl::IsStdAllocator_v<CONTAINER>>
        >
stack(CONTAINER) -> stack<typename CONTAINER::value_type, CONTAINER>;
    // Deduce the template parameters 'VALUE' and 'CONTAINER' from the
    // parameters supplied to the constructor of 'stack'.  This deduction guide
    // does not participate if the parameter meets the requirements for a
    // standard allocator.

template<
    class CONTAINER,
    class ALLOCATOR,
    class = bsl::enable_if_t<bsl::uses_allocator_v<CONTAINER, ALLOCATOR>>
    >
stack(CONTAINER, ALLOCATOR) -> stack<typename CONTAINER::value_type, CONTAINER>;
    // Deduce the template parameters 'VALUE' and 'CONTAINER' from the
    // parameters supplied to the constructor of 'stack'.  This deduction
    // guide does not participate unless the supplied allocator is convertible
    // to the underlying container's 'allocator_type'.
#endif

// FREE OPERATORS
template <class VALUE, class CONTAINER>
bool operator==(const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs);
    // Return 'true' if the specified 'lhs' and 'rhs' objects have the same
    // value, and 'false' otherwise.  Two 'stack' objects 'lhs' and 'rhs' have
    // the same value if they have the same number of elements, and each
    // element in the ordered sequence of elements of 'lhs' has the same value
    // as the corresponding element in the ordered sequence of elements of
    // 'rhs'.  This method requires that the (template parameter) type 'VALUE'
    // be 'equality-comparable' (see {Requirements on 'VALUE'}).

template <class VALUE, class CONTAINER>
bool operator!=(const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs);
    // Return 'true' if the specified 'lhs' and 'rhs' objects do not have the
    // same value, and 'false' otherwise.  Two 'stack' objects 'lhs' and 'rhs'
    // do not have the same value if they do not have the same number of
    // elements, or some element in the ordered sequence of elements of 'lhs'
    // does not have the same value as the corresponding element in the ordered
    // sequence of elements of 'rhs'.  This method requires that the (template
    // parameter) type 'VALUE' be 'equality-comparable' (see {Requirements on
    // 'VALUE'}).

template <class VALUE, class CONTAINER>
bool operator< (const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs);
    // Return 'true' if the value of the specified 'lhs' stack is
    // lexicographically less than that of the specified 'rhs' stack, and
    // 'false' otherwise.  Given iterators 'i' and 'j' over the respective
    // sequences '[lhs.begin() .. lhs.end())' and '[rhs.begin() .. rhs.end())',
    // the value of stack 'lhs' is lexicographically less than that of stack
    // 'rhs' if 'true == *i < *j' for the first pair of corresponding iterator
    // positions where '*i < *j' and '*j < *i' are not both 'false'.  If no
    // such corresponding iterator position exists, the value of 'lhs' is
    // lexicographically less than that of 'rhs' if 'lhs.size() < rhs.size()'.
    // This method requires that 'operator<', inducing a total order, be
    // defined for 'value_type'.

template <class VALUE, class CONTAINER>
bool operator> (const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs);
    // Return 'true' if the value of the specified 'lhs' stack is
    // lexicographically greater than that of the specified 'rhs' stack, and
    // 'false' otherwise.  The value of stack 'lhs' is lexicographically
    // greater than that of stack 'rhs' if 'rhs' is lexicographically less than
    // 'lhs' (see 'operator<').  This method requires that 'operator<',
    // inducing a total order, be defined for 'value_type'.  Note that this
    // operator returns 'rhs < lhs'.

template <class VALUE, class CONTAINER>
bool operator<=(const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs);
    // Return 'true' if the value of the specified 'lhs' stack is
    // lexicographically less than or equal to that of the specified 'rhs'
    // stack, and 'false' otherwise.  The value of stack 'lhs' is
    // lexicographically less than or equal to that of stack 'rhs' if 'rhs' is
    // not lexicographically less than 'lhs' (see 'operator<').  This method
    // requires that 'operator<', inducing a total order, be defined for
    // 'value_type'.  Note that this operator returns '!(rhs < lhs)'.

template <class VALUE, class CONTAINER>
bool operator>=(const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs);
    // Return 'true' if the value of the specified 'lhs' stack is
    // lexicographically greater than or equal to that of the specified 'rhs'
    // stack, and 'false' otherwise.  The value of stack 'lhs' is
    // lexicographically greater than or equal to that of stack 'rhs' if 'lhs'
    // is not lexicographically less than 'rhs' (see 'operator<').  This method
    // requires that 'operator<', inducing a total order, be defined for
    // 'value_type'.  Note that this operator returns '!(lhs < rhs)'.

// FREE FUNCTIONS
template <class VALUE, class CONTAINER>
void swap(stack<VALUE, CONTAINER>& lhs,
          stack<VALUE, CONTAINER>& rhs)
                                    BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(false);
    // Swap the value of the specified 'lhs' stack with the value of the
    // specified 'rhs' stack.

//=============================================================================
//                  TEMPLATE AND INLINE FUNCTION DEFINITIONS
//=============================================================================

                             // -----------
                             // class stack
                             // -----------

// CREATORS
template <class VALUE, class CONTAINER>
inline
stack<VALUE, CONTAINER>::stack()
: c()
{
}

template <class VALUE, class CONTAINER>
inline
stack<VALUE, CONTAINER>::stack(const CONTAINER& container)
: c(container)
{
}

template <class VALUE, class CONTAINER>
inline
stack<VALUE, CONTAINER>::stack(BloombergLP::bslmf::MovableRef<stack> original)
: c(MoveUtil::move(MoveUtil::access(original).c))
{
}

template <class VALUE, class CONTAINER>
template <class ALLOCATOR>
inline
stack<VALUE, CONTAINER>::stack(const ALLOCATOR& basicAllocator,
           typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                              ALLOCATOR>::type *)
: c(basicAllocator)
{
}

template <class VALUE, class CONTAINER>
template <class ALLOCATOR>
inline
stack<VALUE, CONTAINER>::stack(
    const CONTAINER& container,
    const ALLOCATOR& basicAllocator,
    typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                       ALLOCATOR>::type *)
: c(container, basicAllocator)
{
}

template <class VALUE, class CONTAINER>
inline
stack<VALUE, CONTAINER>::stack(const stack& original)
: c(original.c)
{
}

template <class VALUE, class CONTAINER>
template <class ALLOCATOR>
inline
stack<VALUE, CONTAINER>::stack(
    const stack&     original,
    const ALLOCATOR& basicAllocator,
    typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                       ALLOCATOR>::type *)
: c(original.c, basicAllocator)
{
}

template <class VALUE, class CONTAINER>
inline
stack<VALUE, CONTAINER>::stack(BloombergLP::bslmf::MovableRef<CONTAINER>
                                                                     container)
: c(MoveUtil::move(container))
{
}

template <class VALUE, class CONTAINER>
template <class ALLOCATOR>
inline
stack<VALUE, CONTAINER>::stack(
    BloombergLP::bslmf::MovableRef<CONTAINER> container,
    const ALLOCATOR&                          basicAllocator,
    typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                       ALLOCATOR>::type *)
: c(MoveUtil::move(container), basicAllocator)
{
}

template <class VALUE, class CONTAINER>
template <class ALLOCATOR>
inline
stack<VALUE, CONTAINER>::stack(
    BloombergLP::bslmf::MovableRef<stack> original,
    const ALLOCATOR&                      basicAllocator,
    typename enable_if<bsl::uses_allocator<CONTAINER, ALLOCATOR>::value,
                       ALLOCATOR>::type *)
: c(MoveUtil::move(MoveUtil::access(original).c), basicAllocator)
{
}

// MANIPULATORS
template <class VALUE, class CONTAINER>
inline
stack<VALUE, CONTAINER>& stack<VALUE, CONTAINER>::operator=(const stack& rhs)
{
    c = rhs.c;

    return *this;
}

template <class VALUE, class CONTAINER>
inline
stack<VALUE, CONTAINER>& stack<VALUE, CONTAINER>::operator=(
                                     BloombergLP::bslmf::MovableRef<stack> rhs)
                                     BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(false)
{
    c = MoveUtil::move(MoveUtil::access(rhs).c);
    return *this;
}

#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
template <class VALUE, class CONTAINER>
template <class... Args>
inline
typename stack<VALUE, CONTAINER>::reference
stack<VALUE, CONTAINER>::emplace(Args&&... args)
{
    c.emplace_back(BSLS_COMPILERFEATURES_FORWARD(Args,args)...);
    return top();
}
#endif

template <class VALUE, class CONTAINER>
inline
void stack<VALUE, CONTAINER>::pop()
{
    BSLS_ASSERT_SAFE(!empty());

    c.pop_back();
}

template <class VALUE, class CONTAINER>
inline
void stack<VALUE, CONTAINER>::push(const value_type& value)
{
    c.push_back(value);
}

template <class VALUE, class CONTAINER>
inline
void stack<VALUE, CONTAINER>::push(BloombergLP::bslmf::MovableRef<value_type>
                                                                         value)
{
    c.push_back(MoveUtil::move(value));
}

template <class VALUE, class CONTAINER>
inline
void stack<VALUE, CONTAINER>::swap(stack& other)
    BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(
                                   bsl::is_nothrow_swappable<CONTAINER>::value)
{
    BloombergLP::bslalg::SwapUtil::swap(&c, &other.c);
}

template <class VALUE, class CONTAINER>
inline
typename CONTAINER::reference stack<VALUE, CONTAINER>::top()
{
    BSLS_ASSERT_SAFE(!empty());

    return c.back();
}

// ACCESSORS
template <class VALUE, class CONTAINER>
inline
bool stack<VALUE, CONTAINER>::empty() const
{
    return 0 == c.size();
}

template <class VALUE, class CONTAINER>
inline
typename CONTAINER::size_type stack<VALUE, CONTAINER>::size() const
{
    return c.size();
}

template <class VALUE, class CONTAINER>
inline
typename CONTAINER::const_reference stack<VALUE, CONTAINER>::top() const
{
    return c.back();
}

// FREE OPERATORS
template <class VALUE, class CONTAINER>
inline
bool operator==(const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs)
{
    return lhs.c == rhs.c;
}

template <class VALUE, class CONTAINER>
inline
bool operator!=(const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs)
{
    return lhs.c != rhs.c;
}

template <class VALUE, class CONTAINER>
inline
bool operator< (const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs)
{
    return lhs.c < rhs.c;
}

template <class VALUE, class CONTAINER>
inline
bool operator> (const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs)
{
    return lhs.c > rhs.c;
}

template <class VALUE, class CONTAINER>
inline
bool operator<=(const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs)
{
    return lhs.c <= rhs.c;
}

template <class VALUE, class CONTAINER>
inline
bool operator>=(const stack<VALUE, CONTAINER>& lhs,
                const stack<VALUE, CONTAINER>& rhs)
{
    return lhs.c >= rhs.c;
}

// FREE FUNCTIONS
template <class VALUE, class CONTAINER>
inline
void swap(stack<VALUE, CONTAINER>& lhs,
          stack<VALUE, CONTAINER>& rhs)
                                     BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(false)
{
    lhs.swap(rhs);
}

}  // close namespace bsl

#endif // End C++11 code

#endif

// ----------------------------------------------------------------------------
// Copyright 2016 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------