// bslstl_iterator.h                                                  -*-C++-*-
#ifndef INCLUDED_BSLSTL_ITERATOR
#define INCLUDED_BSLSTL_ITERATOR

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

//@PURPOSE: Provide basic iterator traits, adaptors, and utilities.
//
//@CLASSES:
//  bsl::iterator_traits: information about iterator associated types
//  bsl::reverse_iterator: bring in 'std::reverse_iterator'
//  bsl::distance: global function to calculate iterator distance
//
//@CANONICAL_HEADER: bsl_iterator.h
//
//@SEE_ALSO: bslstl_forwarditerator, bslstl_bidirectionaliterator,
//           bslstl_randomaccessiterator, C++ Standard
//
//@DESCRIPTION: This component is for internal use only.  Please include
// '<bsl_iterator.h>' directly.  This component provides the facilities of the
// iterators library from the C++ Standard, including iterator primitives
// (24.4), iterator adaptors (24.5), and stream iterators (24.6).
//
///Usage
///-----
// In this section we show intended use of this component.
//
///Example 1: Using Iterators to Traverse a Container
/// - - - - - - - - - - - - - - - - - - - - - - - - -
// In this example, we will use the 'bsl::iterator' and 'bsl::reverse_iterator'
// to traverse an iterable container type.
//
// Suppose that we have an iterable container template type 'MyFixedSizeArray'.
// An instantiation of 'MyFixedSizeArray' represents an array having fixed
// number of elements, which is a parameter passed to the class constructor
// during construction.  A traversal of 'MyFixedSizeArray' can be accomplished
// using basic iterators (pointers) as well as reverse iterators.
//
// First, we create a elided definition of the template container class,
// 'MyFixedSizeArray', which provides mutable and constant iterators of
// template type 'bsl::iterator' and 'reverse_iterator':
//..
//  template <class VALUE, int SIZE>
//  class MyFixedSizeArray
//      // This is a container that contains a fixed number of elements.  The
//      // number of elements is specified upon construction and can not be
//      // changed afterwards.
//  {
//      // DATA
//      VALUE  d_array[SIZE];  // storage of the container
//
//    public:
//      // PUBLIC TYPES
//      typedef VALUE value_type;
//..
// Here, we define mutable and constant iterators and reverse iterators:
//..
//      typedef VALUE                                  *iterator;
//      typedef VALUE const                            *const_iterator;
//      typedef bsl::reverse_iterator<iterator>         reverse_iterator;
//      typedef bsl::reverse_iterator<const_iterator>   const_reverse_iterator;
//
//      // CREATORS
//      //! MyFixedSizeArray() = default;
//          // Create a 'MyFixedSizeArray' object having the parameterized
//          // 'SIZE' elements of the parameterized type 'VALUE'.
//
//      //! MyFixedSizeArray(const MyFixedSizeArray& original) = default;
//          // Create a 'MyFixedSizeArray' object having same number of
//          // elements as that of the specified 'rhs', and the same value of
//          // each element as that of corresponding element in 'rhs'.
//
//      //! ~MyFixedSizeArray() = default;
//          // Destroy this object.
//..
// Now, we define the 'begin' and 'end' methods to return basic iterators
// ('VALUE*' and 'const VALUE*'), and the 'rbegin' and 'rend' methods to return
// reverse iterators ('bsl::reverse_iterator<VALUE*>' and
// 'bsl::reverse_iterator<const VALUE*>) type:
//..
//      // MANIPULATORS
//      iterator begin();
//          // Return the basic iterator providing modifiable access to the
//          // first valid element of this object.
//
//      iterator end();
//          // Return the basic iterator providing modifiable access to the
//          // position one after the last valid element of this object.
//
//      reverse_iterator rbegin();
//          // Return the reverse iterator providing modifiable access to the
//          // last valid element of this object.
//
//      reverse_iterator rend();
//          // Return the reverse iterator providing modifiable access to the
//          // position one before the first valid element of this object.
//
//      VALUE& operator[](int i);
//          // Return the reference providing modifiable access of the
//          // specified 'i'th element of this object.
//
//      // ACCESSORS
//      const_iterator begin() const;
//          // Return the basic iterator providing non-modifiable access to the
//          // first valid element of this object.
//
//      const_iterator end() const;
//          // Return the basic iterator providing non-modifiable access to the
//          // position one after the last valid element of this object.
//
//      const_reverse_iterator rbegin() const;
//          // Return the reverse iterator providing non-modifiable access to
//          // the last valid element of this object.
//
//      const_reverse_iterator rend() const;
//          // Return the reverse iterator providing non-modifiable access to
//          // the position one before the first valid element of this object.
//
//      int size() const;
//          // Return the number of elements contained in this object.
//
//      const VALUE& operator[](int i) const;
//          // Return the reference providing non-modifiable access of the
//          // specified 'i'th element of this object.
//  };
//
//  // ...
//..
// Then, we create a 'MyFixedSizeArray' and initialize its elements:
//..
//  // Create a fixed array having five elements.
//
//  MyFixedSizeArray<int, 5> fixedArray;
//
//  // Initialize the values of each element in the fixed array.
//
//  for (int i = 0; i < fixedArray.size(); ++i) {
//      fixedArray[i] = i + 1;
//  }
//..
// Next, we generate reverse iterators using the 'rbegin' and 'rend' methods of
// the fixed array object:
//..
//  MyFixedSizeArray<int, 5>::reverse_iterator rstart  = fixedArray.rbegin();
//  MyFixedSizeArray<int, 5>::reverse_iterator rfinish = fixedArray.rend();
//..
// Now, we note that we could have acquired the iterators and container size by
// calling the appropriate free functions:
//..
//  assert(rstart  == bsl::rbegin(fixedArray));
//  assert(rfinish == bsl::rend(  fixedArray));
//
//  assert(fixedArray.size() == bsl::size(fixedArray));
//  assert(rfinish - rstart  == bsl::ssize(fixedArray));
//..
// Finally, we traverse the fixed array again in reverse order using the two
// generated reverse iterators:
//..
//  printf("Traverse array using reverse iterator:\n");
//  while (rstart != rfinish) {
//      printf("\tElement: %d\n", *rstart);
//      ++rstart;
//  }
//..
// The preceding loop produces the following output on 'stdout':
//..
//  Traverse array using reverse iterator:
//       Element: 5
//       Element: 4
//       Element: 3
//       Element: 2
//       Element: 1
//..

#include <bslscm_version.h>

#include <bsls_compilerfeatures.h>
#include <bsls_keyword.h>
#include <bsls_libraryfeatures.h>
#include <bsls_platform.h>

#include <cstddef>

#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
#include <bsls_nativestd.h>
#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES

#if 201703L <= BSLS_COMPILERFEATURES_CPLUSPLUS ||                             \
         (defined(BSLS_PLATFORM_CMP_MSVC) && BSLS_PLATFORM_CMP_VERSION >= 1900)
# define BSLSTL_ITERATOR_SIZE_NATIVE 1
#else
# define BSLSTL_ITERATOR_SIZE_NATIVE 0
#endif

#if 201703L < BSLS_COMPILERFEATURES_CPLUSPLUS
# define BSLSTL_ITERATOR_SSIZE_NATIVE 1
#else
# define BSLSTL_ITERATOR_SSIZE_NATIVE 0
#endif

#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)    &&                    \
    201103L <= BSLS_COMPILERFEATURES_SUPPORT_CPLUSPLUS
# define BSLSTL_ITERATOR_SSIZE_ADVANCED_IMPL 1
#else
# define BSLSTL_ITERATOR_SSIZE_ADVANCED_IMPL 0
#endif

#if !BSLSTL_ITERATOR_SSIZE_NATIVE && BSLSTL_ITERATOR_SSIZE_ADVANCED_IMPL
#include <type_traits>    // 'common_type', 'make_signed'
#endif

#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
# include <initializer_list>
#endif

#include <iterator>

#if defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD)
# define BSLSTL_ITERATOR_IMPLEMENT_CPP11_REVERSE_ITERATOR 1
# define BSLSTL_ITERATOR_PROVIDE_SUN_CPP98_FIXES 1
#endif

namespace bsl {
// Import selected symbols into bsl namespace

// 24.3 primitives
using std::input_iterator_tag;
using std::output_iterator_tag;
using std::forward_iterator_tag;
using std::bidirectional_iterator_tag;
using std::random_access_iterator_tag;
using std::iterator;

// 24.3.4 iterator operations
using std::advance;

// 24.3.4 predefined iterators
using std::back_insert_iterator;
using std::back_inserter;
using std::front_insert_iterator;
using std::front_inserter;
using std::insert_iterator;
using std::inserter;

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY
// 24.5 predefined iterators (C++14)
using std::make_reverse_iterator;
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY

// 24.5 stream iterators
using std::istream_iterator;
using std::ostream_iterator;
using std::istreambuf_iterator;
using std::ostreambuf_iterator;

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
using std::move_iterator;
using std::make_move_iterator;
using std::next;
using std::prev;
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY

#if defined(BSLSTL_ITERATOR_PROVIDE_SUN_CPP98_FIXES)

// Sun does not provide 'std::iterator_traits' at all.  We will provide our own
// in namespace 'bsl'.

                        // =========================
                        // class bsl::IteratorTraits
                        // =========================

template <class ITER>
struct iterator_traits {
    // This 'struct' will provide access to iterator traits.

    // TYPES
    typedef typename ITER::iterator_category iterator_category;
    typedef typename ITER::value_type        value_type;
    typedef typename ITER::difference_type   difference_type;
    typedef typename ITER::pointer           pointer;
    typedef typename ITER::reference         reference;
};

// SPECIALIZATIONS
template <class TYPE>
struct iterator_traits<const TYPE *> {
    // This specialization of 'iterator_traits' will match pointer types to a
    // parameterized non-modifiable 'TYPE'.

    // TYPES
    typedef std::random_access_iterator_tag iterator_category;
    typedef TYPE                            value_type;
    typedef std::ptrdiff_t                  difference_type;
    typedef const TYPE*                     pointer;
    typedef const TYPE&                     reference;
};

template <class TYPE>
struct iterator_traits<TYPE *> {
    // This specialization of 'iterator_traits' will match pointer types to a
    // parameterized modifiable 'TYPE'.

    // TYPES
    typedef std::random_access_iterator_tag iterator_category;
    typedef TYPE                            value_type;
    typedef std::ptrdiff_t                  difference_type;
    typedef TYPE*                           pointer;
    typedef TYPE&                           reference;
};
#else
// Just use the native version
using std::iterator_traits;
#endif

#if defined(BSLSTL_ITERATOR_IMPLEMENT_CPP11_REVERSE_ITERATOR)
// Working around a sun compiler bug where 'std::reverse_iterator' takes 6
// (with 3 default) template arguments instead of 1, which is not standard
// compliant.  Inherit from 'std::reverse_iterator'.  For reference, the
// signature of sun's 'std::reverse_iterator' is:
//..
//  template <class Iterator,
//            class Category,
//            class T,
//            class Reference = T &,
//            class Pointer = T *,
//            class Distance = ptrdiff_t>
//  class reverse_iterator;
//..

                        // ===========================
                        // class bsl::reverse_iterator
                        // ===========================

template <class ITER>
class reverse_iterator :
    public std::reverse_iterator<
                             ITER,
                             typename iterator_traits<ITER>::iterator_category,
                             typename iterator_traits<ITER>::value_type,
                             typename iterator_traits<ITER>::reference,
                             typename iterator_traits<ITER>::pointer> {
    // This class provides a template iterator adaptor that iterates from the
    // end of the sequence defined by the (template parameter) type 'ITER' to
    // the beginning of that sequence.  The type 'ITER' shall meet all the
    // requirements of a bidirectional iterator [24.2.6].  The element sequence
    // generated in this reversed iteration is referred as "reverse iteration
    // sequence" in the following class level documentation.  The fundamental
    // relation between a reverse iterator and its corresponding iterator 'i'
    // of type 'ITER' is established by the identity
    // '&*(reverse_iterator(i)) == &*(i - 1)'.  This template meets the
    // requirement of reverse iterator adaptor defined in C++11 standard
    // [24.5.1].

    // PRIVATE TYPES
    typedef std::reverse_iterator<
                 ITER,
                 typename iterator_traits<ITER>::iterator_category,
                 typename iterator_traits<ITER>::value_type,
                 typename iterator_traits<ITER>::reference,
                 typename iterator_traits<ITER>::pointer>                 Base;

  public:
    // For convenience:

    typedef typename reverse_iterator::difference_type difference_type;

    // CREATORS
    reverse_iterator();
        // Create the default value for this reverse iterator.  The
        // default-constructed reverse iterator does not have a singular value
        // unless an object of the type specified by the template parameter
        // 'ITER' has a singular value after default construction.

    explicit reverse_iterator(ITER base);
        // Create a reverse iterator using the specified 'base' of the
        // (template parameter) type 'ITER'.

    template <class OTHER_ITER>
    reverse_iterator(const reverse_iterator<OTHER_ITER>& original);
        // Create a reverse iterator having the same value as the specified
        // 'original'.

    // MANIPULATORS
    reverse_iterator& operator++();
        // Increment to the next element in the reverse iteration sequence and
        // return a reference providing modifiable access to this reverse
        // iterator.  The behavior is undefined if, on entry, this reverse
        // iterator has the past-the-end value for a reverse iterator over the
        // underlying sequence.

    reverse_iterator  operator++(int);
        // Increment to the next element in the reverse iteration sequence and
        // return a reverse iterator having the pre-increment value of this
        // reverse iterator.  The behavior is undefined if, on entry, this
        // reverse iterator has the past-the-end value for a reverse iterator
        // over the underlying sequence.

    reverse_iterator& operator+=(difference_type n);
        // Increment by the specified 'n' number of elements in the reverse
        // iteration sequence and return a reference providing modifiable
        // access to this reverse iterator.  The behavior is undefined unless
        // this reverse iterator, after incrementing by 'n', is within the
        // bounds of the underlying sequence.  Note that the (template
        // parameter) type 'ITER' shall meet the requirements of a random
        // access iterator.

    reverse_iterator& operator--();
        // Decrement to the previous element in the reverse iteration sequence
        // and return a reference providing modifiable access to this reverse
        // iterator.  The behavior is undefined if, on entry, this reverse
        // iterator has the same value as a reverse iterator to the start of
        // the underlying sequence.

    reverse_iterator  operator--(int);
        // Decrement to the previous element in the reverse iteration sequence
        // and return a reverse iterator having the pre-decrement value of this
        // reverse iterator.  The behavior is undefined if, on entry, this
        // reverse iterator has the same value as a reverse iterator to the
        // start of the underlying sequence.

    reverse_iterator& operator-=(difference_type n);
        // Decrement by the specified 'n' number of elements in the reverse
        // iteration sequence and return a reference providing modifiable
        // access to this reverse iterator.  The behavior is undefined unless
        // this reverse iterator, after decrementing by 'n', is within the
        // bounds of the underlying sequence.  Note that the (template
        // parameter) type 'ITER' shall meet the requirements of a random
        // access iterator.

    // ACCESSORS
    reverse_iterator operator+(difference_type n) const;
        // Return a reverse iterator having the same value as that of
        // incrementing this reverse iterator by the specified 'n' number of
        // elements in the reverse iteration sequence.  The behavior is
        // undefined unless this reverse iterator, if increments by 'n', would
        // be within the bounds of the underlying sequence.  Note that the
        // (template parameter) type 'ITER' shall meet the requirements of a
        // random access iterator.

    reverse_iterator operator-(difference_type n) const;
        // Return a reverse iterator having the same value as that of
        // decrementing this reverse iterator by the specified 'n' number of
        // elements in the reverse iteration sequence.  The behavior is
        // undefined unless this reverse iterator, if decrements by 'n', would
        // be within the bounds of the underlying sequence.  Note that the
        // (template parameter) type 'ITER' shall meet the requirements of a
        // random access iterator.
};

// FREE OPERATORS
template <class ITER>
inline
bool operator==(const reverse_iterator<ITER>& lhs,
                const reverse_iterator<ITER>& rhs);
    // Return 'true' if the specified 'lhs' reverse iterator has the same value
    // as the specified 'rhs' reverse iterator, and 'false' otherwise.  Two
    // reverse iterators have the same value if they refer to the same element,
    // or both have the past-the-end value for a reverse iterator over the
    // underlying reverse iteration sequence.  The behavior is undefined unless
    // both reverse iterators refer to the same underlying sequence.

template <class ITER1, class ITER2>
inline
bool operator==(const reverse_iterator<ITER1>& lhs,
                const reverse_iterator<ITER2>& rhs);
    // Return 'true' if the specified 'lhs' reverse iterator of the (template
    // parameter) type 'ITER1' has the same value as the specified 'rhs'
    // reverse iterator of the (template parameter) type 'ITER2', and 'false'
    // otherwise.  Two reverse iterators have the same value if they refer to
    // the same element, or both have the past-the-end value for a reverse
    // iterator over the underlying reverse iteration sequence.  The behavior
    // is undefined unless both reverse iterators refer to the same underlying
    // sequence.

template <class ITER>
inline
bool operator!=(const reverse_iterator<ITER>& lhs,
                const reverse_iterator<ITER>& rhs);
    // Return 'true' if the specified 'lhs' reverse iterator does not have the
    // same value as the specified 'rhs' reverse iterator, and 'false'
    // otherwise.  Two reverse iterators do not have the same value if (1) they
    // do not refer to the same element and (2) both do not have the
    // past-the-end value for a reverse iterator over the underlying reverse
    // iteration sequence.  The behavior is undefined unless both reverse
    // iterators refer to the same underlying sequence.

template <class ITER1, class ITER2>
inline
bool operator!=(const reverse_iterator<ITER1>& lhs,
                const reverse_iterator<ITER2>& rhs);
    // Return 'true' if the specified 'lhs' reverse iterator of the (template
    // parameter) type 'ITER1' does not have the same value as the specified
    // 'rhs' reverse iterator of the (template parameter) type 'ITER2', and
    // 'false' otherwise.  Two reverse iterators do not have the same value if
    // (1) they do not refer to the same element and (2) both do not have the
    // past-the-end value for a reverse iterator over the underlying reverse
    // iteration sequence.  The behavior is undefined unless both reverse
    // iterators refer to the same underlying sequence.

template <class ITER>
inline
bool operator<(const reverse_iterator<ITER>& lhs,
               const reverse_iterator<ITER>& rhs);
    // Return 'true' if (1) the specified 'lhs' reverse iterator refers to an
    // element before the specified 'rhs' reverse iterator in the reverse
    // iteration sequence, or (2) 'rhs' (and not 'lhs') has the past-the-end
    // value for a reverse iterator over this sequence, and 'false' otherwise.
    // The behavior is undefined unless both reverse iterators refer to the
    // same underlying sequence.  Note that the (template parameter) type
    // 'ITER' shall meet the requirements of random access iterator.

template <class ITER1, class ITER2>
inline
bool operator<(const reverse_iterator<ITER1>& lhs,
               const reverse_iterator<ITER2>& rhs);
    // Return 'true' if (1) the specified 'lhs' reverse iterator of the
    // (template parameter) type 'ITER1' refers to an element before the
    // specified 'rhs' reverse iterator of the (template parameter) type
    // 'ITER2' in the reverse iteration sequence, or (2) 'rhs' (and not 'lhs')
    // has the past-the-end value for a reverse iterator over this sequence,
    // and 'false' otherwise.  The behavior is undefined unless both reverse
    // iterators refer to the same underlying sequence.  Note that both 'ITER1'
    // and 'ITER2' shall meet the requirements of random access iterator.

template <class ITER>
inline
bool operator>(const reverse_iterator<ITER>& lhs,
               const reverse_iterator<ITER>& rhs);
    // Return 'true' if (1) the specified 'lhs' reverse iterator refers to an
    // element after the specified 'rhs' reverse iterator in the reverse
    // iteration sequence, or (2) 'lhs' (and not 'rhs') has the past-the-front
    // value of an reverse iterator over this sequence, and 'false' otherwise.
    // The behavior is undefined unless both reverse iterators refer to the
    // same underlying sequence.  Note that the (template parameter) type
    // 'ITER' shall meet the requirements of random access iterator.

template <class ITER1, class ITER2>
inline
bool operator>(const reverse_iterator<ITER1>& lhs,
               const reverse_iterator<ITER2>& rhs);
    // Return 'true' if (1) the specified 'lhs' reverse iterator of the
    // (template parameter) type 'ITER1' refers to an element after the
    // specified 'rhs' reverse iterator of the (template parameter) type
    // 'ITER2' in the reverse iteration sequence, or (2) 'lhs' (and not 'rhs')
    // has the past-the-front value of an reverse iterator over this sequence,
    // and 'false' otherwise.  The behavior is undefined unless both reverse
    // iterators refer to the same underlying sequence.  Note that both 'ITER1'
    // and 'ITER2' shall meet the requirements of random access iterator.

template <class ITER>
inline
bool operator<=(const reverse_iterator<ITER>& lhs,
                const reverse_iterator<ITER>& rhs);
    // Return 'true' if (1) the specified 'lhs' reverse iterator has the same
    // value as the specified 'rhs' reverse iterator, or (2) 'lhs' refers to an
    // element before 'rhs' in the reverse iteration sequence, or (3) 'rhs' has
    // the past-the-end value for a reverse iterator over this sequence, and
    // 'false' otherwise.  The behavior is undefined unless both reverse
    // iterators refer to the same underlying sequence.  Note that the
    // (template parameter) type 'ITER' shall meet the requirements of a random
    // access iterator.

template <class ITER1, class ITER2>
inline
bool operator<=(const reverse_iterator<ITER1>& lhs,
                const reverse_iterator<ITER2>& rhs);
    // Return 'true' if (1) the specified 'lhs' reverse iterator of the
    // (template parameter) type 'ITER1' has the same value as the specified
    // 'rhs' reverse iterator of the (template parameter) type 'ITER2', or (2)
    // 'lhs' refers to an element before 'rhs' in the reverse iteration
    // sequence, or (3) 'rhs' has the past-the-end value for a reverse iterator
    // over this sequence, and 'false' otherwise.  The behavior is undefined
    // unless both reverse iterators refer to the same underlying sequence.
    // Note that both 'ITER1' and 'ITER2' shall meet the requirements of a
    // random access iterator.

template <class ITER>
inline
bool operator>=(const reverse_iterator<ITER>& lhs,
                const reverse_iterator<ITER>& rhs);
    // Return 'true' if (1) the specified 'lhs' reverse iterator has the same
    // value as the specified 'rhs' reverse iterator, or (2) 'lhs' has the
    // past-the-end value for a reverse iterator over the underlying reverse
    // iteration sequence, or (3) 'lhs' refers to an element after 'rhs' in
    // this sequence, and 'false' otherwise.  The behavior is undefined unless
    // both reverse iterators refer to the same underlying sequence.  Note that
    // the (template parameter) type 'ITER' shall meet the requirements of
    // random access iterator.

template <class ITER1, class ITER2>
inline
bool operator>=(const reverse_iterator<ITER1>& lhs,
                const reverse_iterator<ITER2>& rhs);
    // Return 'true' if (1) the specified 'lhs' reverse iterator of the
    // (template parameter) type 'ITER1' has the same value as the specified
    // 'rhs' reverse iterator of the (template parameter) type 'ITER2', or (2)
    // 'lhs' has the past-the-end value for a reverse iterator over the
    // underlying reverse iteration sequence, or (3) 'lhs' refers to an element
    // after 'rhs' in this sequence, and 'false' otherwise.  The behavior is
    // undefined unless both reverse iterators refer to the same underlying
    // sequence.  Note that both type 'ITER1' and type 'ITER2' shall meet the
    // requirements of random access iterator.

template <class ITER>
inline
typename reverse_iterator<ITER>::difference_type
operator-(const reverse_iterator<ITER>& lhs,
          const reverse_iterator<ITER>& rhs);
    // Return the distance from the specified 'rhs' reverse iterator to the
    // specified 'lhs' reverse iterator.  The behavior is undefined unless
    // 'lhs' and 'rhs' are reverse iterators into the same underlying sequence.
    // Note that the (template parameter) type 'ITER' shall meet the
    // requirements of random access iterator.  Also note that the result might
    // be negative.

template <class ITER, class DIFF_TYPE>
inline
reverse_iterator<ITER>
operator+(DIFF_TYPE n, const reverse_iterator<ITER>& rhs);
    // Return a reverse iterator to the element at the specified 'n' positions
    // past the specified 'rhs' reverse iterator.  The behavior is undefined
    // unless 'rhs', after incrementing by 'n', is within the bounds of the
    // underlying sequence.  Note that the (template parameter) type 'ITER'
    // shall meet the requirements of random access iterator.
#else
// Just use the native version
using std::reverse_iterator;
#endif

#if defined(BSLSTL_ITERATOR_PROVIDE_SUN_CPP98_FIXES)

                        // ==========================
                        // struct IteratorDistanceImp
                        // ==========================

struct IteratorDistanceImp {
    // This utility class provides a namespace for functions that operate on
    // iterators.

    // CLASS METHODS
    template <class FWD_ITER, class DIFFERENCE_TYPE>
    static void getDistance(DIFFERENCE_TYPE *ret,
                            FWD_ITER         start,
                            FWD_ITER         finish,
                            input_iterator_tag);
        // Return in the specified '*ret' the distance from the specified
        // 'start' iterator to the specified 'finish' iterator.  The behavior
        // is undefined unless 'start' and 'finish' both have the
        // 'input_iterator_tag' into the same underlying sequence, and 'start'
        // is before 'finish' in that sequence.

    template <class FWD_ITER, class DIFFERENCE_TYPE>
    static void getDistance(DIFFERENCE_TYPE *ret,
                            FWD_ITER         start,
                            FWD_ITER         finish,
                            forward_iterator_tag);
        // Return in the specified '*ret' the distance from the specified
        // 'start' iterator to the specified 'finish' iterator.  The behavior
        // is undefined unless 'start' and 'finish' both have the
        // 'forward_iterator_tag' into the same underlying sequence, and
        // 'start' is before 'finish' in that sequence.

    template <class RANDOM_ITER, class DIFFERENCE_TYPE>
    static void getDistance(DIFFERENCE_TYPE *ret,
                            RANDOM_ITER      start,
                            RANDOM_ITER      finish,
                            random_access_iterator_tag);
        // Return in the specified '*ret' the distance from the specified
        // 'start' iterator to the specified 'finish' iterator.  The behavior
        // is undefined unless 'start' and 'finish' both have the
        // 'random_access_iterator_tag' into the same underlying sequence.
        // Note that the result might be negative.
};

template <class ITER>
typename iterator_traits<ITER>::difference_type
distance(ITER start, ITER finish);
    // Return the distance from the specified 'start' iterator to the specified
    // 'finish' iterator.  The behavior is undefined unless 'start' and
    // 'finish' are both into the same underlying sequence, and 'start' is
    // before 'finish' in that sequence.  Note that the (template parameter)
    // type 'ITER' shall meet the requirements of input iterator.
#else
// Just use the native version
using std::distance;
#endif

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_RANGE_FUNCTIONS
using std::begin;
using std::end;
#else
template <class T>
typename T::iterator begin(T& container);
    // Return an iterator providing modifiable access to the first valid
    // element of the specified 'container'.

template <class T>
typename T::const_iterator begin(const T& container);
    // Return an iterator providing non-modifiable access to the first valid
    // element of the specified 'container'.

template<class T, size_t N>
T *begin(T (&array)[N]);
    // Return the address of the modifiable first element in the specified
    // 'array'.

template<class T, size_t N>
const T *begin(const T (&array)[N]);
    // Return the address of the non-modifiable first element in the specified
    // 'array'.

template <class T>
typename T::iterator end(T& container);
    // Return the iterator providing modifiable access to the position one
    // after the last valid element in the specified 'container'.

template <class T>
typename T::const_iterator end(const T& container);
    // Return the iterator providing non-modifiable access to the position one
    // after the last valid element in the specified 'container'.

template<class T, size_t N>
T *end(T (&array)[N]);
    // Return the address of the modifiable element after the last element
    // in the specified 'array'.

template<class T, size_t N>
const T *end(const T (&array)[N]);
    // Return the address of the non-modifiable element after the last element
    // in the specified 'array'.

#endif  // BSLS_LIBRARYFEATURES_HAS_CPP11_RANGE_FUNCTIONS

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP14_RANGE_FUNCTIONS
using std::cbegin;
using std::cend;
using std::rbegin;
using std::rend;
using std::crbegin;
using std::crend;
#else
template <class T>
typename T::const_iterator cbegin(const T& container);
    // Return an iterator providing non-modifiable access to the first valid
    // element of the specified 'container'.

template<class T, size_t N>
const T *cbegin(const T (&array)[N]);
    // Return the address of the non-modifiable first element in the specified
    // 'array'.

template <class T>
typename T::reverse_iterator rbegin(T& container);
    // Return the reverse iterator providing modifiable access to the last
    // valid element of the specified 'container'.

template <class T>
typename T::const_reverse_iterator rbegin(const T& container);
    // Return the reverse iterator providing non-modifiable access to the last
    // valid element of the specified 'container'.

template <class T, size_t N>
reverse_iterator<T *> rbegin(T (&array)[N]);
    // Return the reverse iterator providing modifiable access to the last
    // element of the specified 'array'.

#ifdef BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS
template <class T>
reverse_iterator<const T *> rbegin(std::initializer_list<T> initializerList);
    // Return the reverse iterator providing non-modifiable access to the last
    // element of the specified 'initializerList'.
#endif  // BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS

template <class T>
typename T::const_reverse_iterator crbegin(const T& container);
    // Return the reverse iterator providing non-modifiable access to the last
    // valid element of the specified 'container'.

template <class T, size_t N>
reverse_iterator<const T *> crbegin(const T (&array)[N]);
    // Return the reverse iterator providing non-modifiable access to the last
    // element of the specified 'array'.

template <class T>
typename T::const_iterator cend(const T& container);
    // Return the iterator providing non-modifiable access to the position one
    // after the last valid element in the specified 'container'.

template<class T, size_t N>
const T *cend(const T (&array)[N]);
    // Return the address of the non-modifiable element after the last element
    // in the specified 'array'.

template <class T>
typename T::reverse_iterator rend(T& container);
    // Return the reverse iterator providing modifiable access to the position
    // one before the first valid element in the specified 'container'.

template <class T>
typename T::const_reverse_iterator rend(const T& container);
    // Return the reverse iterator providing non-modifiable access to the
    // position one before the first valid element in the specified
    // 'container'.

template <class T, size_t N>
reverse_iterator<T *> rend(T (&array)[N]);
    // Return the reverse iterator providing modifiable access to the position
    // one before the first element in the specified 'array'.

#ifdef BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS
template <class T>
reverse_iterator<const T *> rend(std::initializer_list<T> initializerList);
    // Return the reverse iterator providing non-modifiable access to the
    // position one before the first element in the specified
    // 'initializerList'.
#endif  // BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS

template <class T>
typename T::const_reverse_iterator crend(const T& container);
    // Return the reverse iterator providing non-modifiable access to the
    // position one before the first element in the specified 'container'.

template <class T, size_t N>
reverse_iterator<const T *> crend(const T (&array)[N]);
    // Return the reverse iterator providing non-modifiable access to the
    // position one before the first element in the specified 'array'.
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP14_RANGE_FUNCTIONS

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES

namespace ranges {

using std::ranges::distance;

}

#endif  // BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES

// ============================================================================
//                      INLINE FUNCTION DEFINITIONS
// ============================================================================

#if defined(BSLSTL_ITERATOR_IMPLEMENT_CPP11_REVERSE_ITERATOR)

                        // ---------------------------
                        // class bsl::reverse_iterator
                        // ---------------------------

// CREATORS
template <class ITER>
inline
reverse_iterator<ITER>::reverse_iterator()
: Base()
{
}

template <class ITER>
inline
reverse_iterator<ITER>::reverse_iterator(ITER base)
: Base(base)
{
}

template <class ITER>
template <class OTHER_ITER>
inline
reverse_iterator<ITER>::reverse_iterator(
                                  const reverse_iterator<OTHER_ITER>& original)
: Base(original.base())
{
}

// MANIPULATORS
template <class ITER>
inline
reverse_iterator<ITER>&
reverse_iterator<ITER>::operator++()
{
    Base::operator++();
    return *this;
}

template <class ITER>
inline
reverse_iterator<ITER>
reverse_iterator<ITER>::operator++(int)
{
    const reverse_iterator tmp(*this);
    this->operator++();
    return tmp;
}

template <class ITER>
inline
reverse_iterator<ITER>&
reverse_iterator<ITER>::operator+=(difference_type n)
{
    Base::operator+=(n);
    return *this;
}

template <class ITER>
inline
reverse_iterator<ITER>&
reverse_iterator<ITER>::operator--()
{
    Base::operator--();
    return *this;
}

template <class ITER>
inline
reverse_iterator<ITER>
reverse_iterator<ITER>::operator--(int)
{
    reverse_iterator tmp(*this);
    this->operator--();
    return tmp;
}

template <class ITER>
inline
reverse_iterator<ITER>&
reverse_iterator<ITER>::operator-=(difference_type n)
{
    Base::operator-=(n);
    return *this;
}

// ACCESSORS
template <class ITER>
inline
reverse_iterator<ITER>
reverse_iterator<ITER>::operator+(difference_type n) const
{
    reverse_iterator tmp(*this);
    tmp += n;
    return tmp;
}

template <class ITER>
inline
reverse_iterator<ITER>
reverse_iterator<ITER>::operator-(difference_type n) const
{
    reverse_iterator tmp(*this);
    tmp -= n;
    return tmp;
}

// FREE OPERATORS
template <class ITER>
inline
bool operator==(const reverse_iterator<ITER>& lhs,
                const reverse_iterator<ITER>& rhs)
{
    typedef std::reverse_iterator<
                 ITER,
                 typename iterator_traits<ITER>::iterator_category,
                 typename iterator_traits<ITER>::value_type,
                 typename iterator_traits<ITER>::reference,
                 typename iterator_traits<ITER>::pointer>                 Base;

    return std::operator==(static_cast<const Base&>(lhs),
                           static_cast<const Base&>(rhs));
}

template <class ITER1, class ITER2>
inline
bool operator==(const reverse_iterator<ITER1>& lhs,
                const reverse_iterator<ITER2>& rhs)
{
    // this is to compare reverse_iterator with const_reverse_iterator

    return lhs.base() == rhs.base();
}

template <class ITER>
inline
bool operator!=(const reverse_iterator<ITER>& lhs,
                const reverse_iterator<ITER>& rhs)
{
    return ! (lhs == rhs);
}

template <class ITER1, class ITER2>
inline
bool operator!=(const reverse_iterator<ITER1>& lhs,
                const reverse_iterator<ITER2>& rhs)
{
    // this is to compare reverse_iterator with const_reverse_iterator

    return ! (lhs == rhs);
}

template <class ITER>
inline
bool operator<(const reverse_iterator<ITER>& lhs,
               const reverse_iterator<ITER>& rhs)
{
    return rhs.base() < lhs.base();
}

template <class ITER1, class ITER2>
inline
bool operator<(const reverse_iterator<ITER1>& lhs,
               const reverse_iterator<ITER2>& rhs)
{
    // this is to compare reverse_iterator with const_reverse_iterator

    return rhs.base() < lhs.base();
}

template <class ITER>
inline
bool operator>(const reverse_iterator<ITER>& lhs,
               const reverse_iterator<ITER>& rhs)
{
    return rhs < lhs;
}

template <class ITER1, class ITER2>
inline
bool operator>(const reverse_iterator<ITER1>& lhs,
               const reverse_iterator<ITER2>& rhs)
{
    return rhs < lhs;
}

template <class ITER>
inline
bool operator<=(const reverse_iterator<ITER>& lhs,
                const reverse_iterator<ITER>& rhs)
{
    return !(rhs < lhs);
}

template <class ITER1, class ITER2>
inline
bool operator<=(const reverse_iterator<ITER1>& lhs,
                const reverse_iterator<ITER2>& rhs)
{
    return !(rhs < lhs);
}

template <class ITER>
inline
bool operator>=(const reverse_iterator<ITER>& lhs,
                const reverse_iterator<ITER>& rhs)
{
    return !(lhs < rhs);
}

template <class ITER1, class ITER2>
inline
bool operator>=(const reverse_iterator<ITER1>& lhs,
                const reverse_iterator<ITER2>& rhs)
{
    return !(lhs < rhs);
}

template <class ITER>
inline
typename reverse_iterator<ITER>::difference_type
operator-(const reverse_iterator<ITER>& lhs,
          const reverse_iterator<ITER>& rhs)
{
    typedef std::reverse_iterator<
                 ITER,
                 typename iterator_traits<ITER>::iterator_category,
                 typename iterator_traits<ITER>::value_type,
                 typename iterator_traits<ITER>::reference,
                 typename iterator_traits<ITER>::pointer>                 Base;

    return std::operator-(static_cast<const Base&>(lhs),
                          static_cast<const Base&>(rhs));
}

template <class ITER, class DIFF_TYPE>
inline
reverse_iterator<ITER>
operator+(DIFF_TYPE n, const reverse_iterator<ITER>& rhs)
{
    return rhs.operator+(n);
}

#endif

                                    // ====
                                    // data
                                    // ====

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_RANGE_FUNCTIONS
using std::data;
#else

template <class CONTAINER>
inline BSLS_KEYWORD_CONSTEXPR
#ifdef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
auto data(CONTAINER& container) -> decltype(container.data())
#else
typename CONTAINER::value_type *data(CONTAINER& container)
#endif
    // Return an pointer providing modifiable access to the first valid
    // element of the specified 'container'.  The 'CONTAINER' template
    // parameter type must provide a 'data' accessor.

{
    return container.data();
}

template <class CONTAINER>
inline BSLS_KEYWORD_CONSTEXPR
#ifdef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
auto data(const CONTAINER& container) -> decltype(container.data())
#else
typename CONTAINER::value_type const *data(const CONTAINER& container)
#endif
    // Return a pointer providing non-modifiable access to the first valid
    // element of the specified 'container'.  The 'CONTAINER' template
    // parameter type must provide a 'data' accessor.
{
    return container.data();
}
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP17_RANGE_FUNCTIONS

                                  // =====
                                  // empty
                                  // =====

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_RANGE_FUNCTIONS
using std::empty;
#else
# ifdef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
template <class CONTAINER>
inline
BSLS_KEYWORD_CONSTEXPR auto empty(const CONTAINER& container)->
                                                    decltype(container.empty())
    // Return whether or not the specified 'container' contains zero elements.
    // The 'CONTAINER' template parameter type must provide a 'empty' accessor.
{
    return container.empty();
}
# else
template <class CONTAINER>
inline
BSLS_KEYWORD_CONSTEXPR bool empty(const CONTAINER& container)
    // Return whether or not the specified 'container' contains zero elements.
    // The 'CONTAINER' template parameter type must provide a 'empty' accessor.
{
    return container.empty();
}
# endif // BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE

template <class TYPE, size_t DIMENSION>
inline
BSLS_KEYWORD_CONSTEXPR bool empty(const TYPE (&)[DIMENSION])
    // Return false (Zero-length arrays are not allowed).
{
    return false;
}

#ifdef BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS
template <class TYPE>
inline
BSLS_KEYWORD_CONSTEXPR bool empty(std::initializer_list<TYPE> initializerList)
    // Return whether of not the specified 'initializerList' contains zero
    // elements.  This is a separate specialization because
    // 'std::initializer_list<TYPE>' does not have an 'empty' member function.
{
    return 0 == initializerList.size();
}
#endif  // BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS

#endif  // BSLS_LIBRARYFEATURES_HAS_CPP17_RANGE_FUNCTIONS

                                  // ====
                                  // size
                                  // ====

#if BSLSTL_ITERATOR_SIZE_NATIVE

using std::size;

#else

# if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)

template <class CONTAINER>
inline
BSLS_KEYWORD_CONSTEXPR auto size(const CONTAINER& container) ->
                                                     decltype(container.size())
    // Return the size of the specified 'container'.  The 'CONTAINER' template
    // parameter type must provide a 'size' accessor.
{
    return container.size();
}

# else

template <class CONTAINER>
inline
BSLS_KEYWORD_CONSTEXPR size_t size(const CONTAINER& container)
    // Return the size of the specified 'container'.  The 'CONTAINER' template
    // parameter type must provide a 'size' accessor.
{
    return container.size();
}

# endif

template <class TYPE, size_t DIMENSION>
inline
BSLS_KEYWORD_CONSTEXPR size_t size(const TYPE (&)[DIMENSION])
    // Return the dimension of the specified array argument.
{
    return DIMENSION;
}

#endif

                                    // =====
                                    // ssize
                                    // =====

#if BSLSTL_ITERATOR_SSIZE_NATIVE

using std::ssize;

#else

# if BSLSTL_ITERATOR_SSIZE_ADVANCED_IMPL

template <class CONTAINER>
inline
BSLS_KEYWORD_CONSTEXPR auto ssize(const CONTAINER& container) ->
                       std::common_type_t<
                                std::ptrdiff_t,
                                std::make_signed_t<decltype(container.size())>>
    // Return the size of the specified 'container'.  The 'CONTAINER' template
    // parameter type must provide a 'size' accessor.
{
    return container.size();
}

# else

template <class CONTAINER>
inline
BSLS_KEYWORD_CONSTEXPR std::ptrdiff_t ssize(const CONTAINER& container)
    // Return the size of the specified 'container'.  The 'CONTAINER' template
    // parameter type must provide a 'size' accessor.
{
    return container.size();
}

# endif

template <class TYPE, std::ptrdiff_t DIMENSION>
inline
BSLS_KEYWORD_CONSTEXPR std::ptrdiff_t ssize(const TYPE (&)[DIMENSION])
    // Return the dimension of the specified array argument.
{
    return DIMENSION;
}

#endif

#undef BSLSTL_ITERATOR_SIZE_NATIVE
#undef BSLSTL_ITERATOR_SSIZE_NATIVE
#undef BSLSTL_ITERATOR_SSIZE_ADVANCED_IMPL

#if defined(BSLSTL_ITERATOR_PROVIDE_SUN_CPP98_FIXES)

                         // --------------------------
                         // struct IteratorDistanceImp
                         // --------------------------

template <class FWD_ITER, class DIFFERENCE_TYPE>
void IteratorDistanceImp::getDistance(DIFFERENCE_TYPE *ret,
                                      FWD_ITER         start,
                                      FWD_ITER         finish,
                                      input_iterator_tag)
{
    DIFFERENCE_TYPE count = 0;
    for ( ; start != finish; ++start) {
        ++count;
    }

    *ret = count;
}

template <class FWD_ITER, class DIFFERENCE_TYPE>
void IteratorDistanceImp::getDistance(DIFFERENCE_TYPE *ret,
                                      FWD_ITER         start,
                                      FWD_ITER         finish,
                                      forward_iterator_tag)
{
    DIFFERENCE_TYPE count = 0;
    for ( ; start != finish; ++start) {
        ++count;
    }

    *ret = count;
}

template <class RANDOM_ITER, class DIFFERENCE_TYPE>
inline
void IteratorDistanceImp::getDistance(DIFFERENCE_TYPE *ret,
                                      RANDOM_ITER      start,
                                      RANDOM_ITER      finish,
                                      random_access_iterator_tag)
{
    *ret = DIFFERENCE_TYPE(finish - start);
}

template <class ITER>
inline
typename iterator_traits<ITER>::difference_type
distance(ITER start, ITER finish)
{
    typedef typename bsl::iterator_traits<ITER>::iterator_category tag;

    typename iterator_traits<ITER>::difference_type ret;
    IteratorDistanceImp::getDistance(&ret, start, finish, tag());
    return ret;
}

#endif  // BSLS_PLATFORM_CMP_SUN && !BDE_BUILD_TARGET_STLPORT

#ifndef BSLS_LIBRARYFEATURES_HAS_CPP11_RANGE_FUNCTIONS
template <class T>
inline
typename T::iterator begin(T& container)
{
    return container.begin();
}

template <class T>
inline
typename T::const_iterator begin(const T& container)
{
    return container.begin();
}

template<class T, size_t N>
inline
T *begin(T (&array)[N])
{
    return array;
}

template<class T, size_t N>
inline
const T *begin(const T (&array)[N])
{
    return array;
}

template <class T>
inline
typename T::iterator end(T& container)
{
    return container.end();
}

template <class T>
inline
typename T::const_iterator end(const T& container)
{
    return container.end();
}

template<class T, size_t N>
inline
T *end(T (&array)[N])
{
    return array + N;
}

template<class T, size_t N>
inline
const T *end(const T (&array)[N])
{
    return array + N;
}

#endif  // BSLS_LIBRARYFEATURES_HAS_CPP11_RANGE_FUNCTIONS

#ifndef BSLS_LIBRARYFEATURES_HAS_CPP14_RANGE_FUNCTIONS
template <class T>
inline
typename T::const_iterator cbegin(const T& container)
{
    return begin(container);
}

template<class T, size_t N>
inline
const T *cbegin(const T (&array)[N])
{
    return begin(array);
}

template <class T>
inline
typename T::reverse_iterator rbegin(T& container)
{
    return container.rbegin();
}

template <class T>
inline
typename T::const_reverse_iterator rbegin(const T& container)
{
    return container.rbegin();
}

template <class T, size_t N>
inline
reverse_iterator<T *> rbegin(T (&array)[N])
{
    return reverse_iterator<T *>(array + N);
}

#ifdef BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS
template <class T>
inline
reverse_iterator<const T *> rbegin(std::initializer_list<T> initializerList)
{
    return reverse_iterator<const T *>(initializerList.end());
}
#endif  // BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS

template <class T>
inline
typename T::const_reverse_iterator crbegin(const T& container)
{
    return rbegin(container);
}

template <class T, size_t N>
inline
reverse_iterator<const T *> crbegin(const T (&array)[N])
{
    return reverse_iterator<const T *>(array + N);
}

template <class T>
inline
typename T::const_iterator cend(const T& container)
{
    return end(container);
}

template<class T, size_t N>
inline
const T *cend(const T (&array)[N])
{
    return end(array);
}

template <class T>
inline
typename T::reverse_iterator rend(T& container)
{
    return container.rend();
}

template <class T>
inline
typename T::const_reverse_iterator rend(const T& container)
{
    return container.rend();
}

template <class T, size_t N>
inline
reverse_iterator<T *> rend(T (&array)[N])
{
    return reverse_iterator<T *>(array);
}

#ifdef BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS
template <class T>
inline
reverse_iterator<const T *> rend(std::initializer_list<T> initializerList)
{
    return reverse_iterator<const T *>(initializerList.begin());
}
#endif  // BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS

template <class T>
typename T::const_reverse_iterator crend(const T& container)
{
    return rend(container);
}

template <class T, size_t N>
inline
reverse_iterator<const T *> crend(const T (&array)[N])
{
    return reverse_iterator<const T *>(array);
}
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP14_RANGE_FUNCTIONS

}  // close namespace bsl

#endif

// ----------------------------------------------------------------------------
// Copyright 2013 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 ----------------------------------