// utility standard header -*-c++-*-
// Copyright 2009-2017 IAR Systems AB.
#ifndef _UTILITY_
#define _UTILITY_

#ifndef _SYSTEM_BUILD
  #pragma system_include
#endif

#include <xstddef>
#include <iosfwd>
#include <type_traits>

namespace std {

// TEMPLATE FUNCTION iter_swap (from <xutility>)
template<class _Ty> inline
void swap(_Ty&, _Ty&)
  _NOEXCEPT_OP(   is_nothrow_move_constructible<_Ty>::value
               && is_nothrow_move_assignable<_Ty>::value);

template<class _FwdIt1,
         class _FwdIt2> inline
void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right)
{       // swap *_Left and *_Right
  swap(*_Left, *_Right);
}

// TEMPLATE FUNCTION swap
template<class _Ty,
         size_t _Size> inline
void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size])
  _NOEXCEPT_OP(_NOEXCEPT_OP(swap(*_Left, *_Right)))
{       // exchange arrays stored at _Left and _Right
  if (&_Left != &_Right)
  {       // worth swapping, swap ranges
    for (size_t _I = 0; _I < _Size; ++_I)
      swap(_Left[_I], _Right[_I]);
  }
}

template<class _Ty> inline
void swap(_Ty& _Left, _Ty& _Right)
  _NOEXCEPT_OP(is_nothrow_move_constructible<_Ty>::value
               && is_nothrow_move_assignable<_Ty>::value)
{       // exchange values stored at _Left and _Right
  _Ty _Tmp = _Move(_Left);
  _Left = _Move(_Right);
  _Right = _Move(_Tmp);
}

// TEMPLATE FUNCTION _Swap_adl
template<class _Ty> inline
void _Swap_adl(_Ty& _Left, _Ty& _Right)
  _NOEXCEPT_OP(_NOEXCEPT_OP(swap(_Left, _Right)))
{       // exchange values stored at _Left and _Right, using ADL
  swap(_Left, _Right);
}

// STRUCT piecewise_construct_t
struct piecewise_construct_t
{       // tag type for pair tuple arguments
};

constexpr piecewise_construct_t piecewise_construct{};

// TEMPLATE STRUCT pair

template<class...>
class tuple;

template<class _Ty1,
         class _Ty2>
struct pair
{       // store a pair of values
  typedef pair<_Ty1, _Ty2> _Myt;
  typedef _Ty1 first_type;
  typedef _Ty2 second_type;

  constexpr pair()
    : first(), second()
  {       // default construct
  }

  constexpr pair(const _Ty1& _Val1, const _Ty2& _Val2)
    : first(_Val1), second(_Val2)
  {       // construct from specified values
  }

  pair(const pair&) = default;
  pair(pair&&) = default;

  template<class _Other1,
           class _Other2,
           class = typename enable_if<
                is_convertible<const _Other1&, _Ty1>::value
             && is_convertible<const _Other2&, _Ty2>::value,
             void>::type>
  constexpr pair(const pair<_Other1, _Other2>& _Right)
    : first(_Right.first), second(_Right.second)
  {       // construct from compatible pair
  }

  template<class _Other1,
           class _Other2>
  _Myt& operator=(const pair<_Other1, _Other2>& _Right)
  {       // assign from compatible pair
    first = _Right.first;
    second = _Right.second;
    return *this;
  }

  template<class _Tuple1,
           class _Tuple2,
           size_t... _Indexes1,
           size_t... _Indexes2> inline
  pair(_Tuple1& _Val1,
       _Tuple2& _Val2,
       integer_sequence<size_t, _Indexes1...>,
       integer_sequence<size_t, _Indexes2...>);

  template<class... _Types1,
           class... _Types2> inline
  pair(piecewise_construct_t,
       tuple<_Types1...> _Val1,
       tuple<_Types2...> _Val2);

  template<class _Other1,
           class _Other2,
           class = typename enable_if<
             is_convertible<_Other1, _Ty1>::value
             && is_convertible<_Other2, _Ty2>::value,
             void>::type>
  constexpr pair(_Other1&& _Val1, _Other2&& _Val2)
    _NOEXCEPT_OP((   is_nothrow_constructible<_Ty1, _Other1&&>::value
                  && is_nothrow_constructible<_Ty2, _Other2&&>::value))
    : first(std::forward<_Other1>(_Val1)),
      second(std::forward<_Other2>(_Val2))
  {       // construct from moved values
  }

  template<class _Other1,
           class _Other2,
           class = typename enable_if<
                is_convertible<_Other1, _Ty1>::value
             && is_convertible<_Other2, _Ty2>::value,
             void>::type>
  constexpr pair(pair<_Other1, _Other2>&& _Right)
    _NOEXCEPT_OP((   is_nothrow_constructible<_Ty1, _Other1&&>::value
                  && is_nothrow_constructible<_Ty2, _Other2&&>::value))
    : first(std::forward<_Other1>(_Right.first)),
      second(std::forward<_Other2>(_Right.second))
  {       // construct from moved compatible pair
  }

  template<class _Other1,
           class _Other2>
  _Myt& operator=(pair<_Other1, _Other2>&& _Right)
  {       // assign from moved compatible pair
    first = std::forward<_Other1>(_Right.first);
    second = std::forward<_Other2>(_Right.second);
    return *this;
  }

  _Myt& operator=(_Myt&& _Right)
    _NOEXCEPT_OP((   is_nothrow_move_assignable<_Ty1>::value
                  && is_nothrow_move_assignable<_Ty2>::value))
  {       // assign from moved pair
    first = std::forward<_Ty1>(_Right.first);
    second = std::forward<_Ty2>(_Right.second);
    return *this;
  }

  void swap(_Myt& _Right)
    _NOEXCEPT_OP(   _NOEXCEPT_OP(_Swap_adl(this->first, _Right.first))
                 && _NOEXCEPT_OP(_Swap_adl(this->second, _Right.second)))
  {       // exchange contents with _Right
    if (this != &_Right)
    {       // different, worth swapping
      _Swap_adl(first, _Right.first);
      _Swap_adl(second, _Right.second);
    }
  }

  _Myt& operator=(const _Myt& _Right)
  {       // assign from copied pair
    first = _Right.first;
    second = _Right.second;
    return *this;
  }

  _Ty1 first;     // the first stored value
  _Ty2 second;    // the second stored value
};

// pair TEMPLATE FUNCTIONS
template<class _Ty1,
         class _Ty2> inline
void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right)
  _NOEXCEPT_OP(_NOEXCEPT_OP(_Left.swap(_Right)))
{       // swap _Left and _Right pairs
  _Left.swap(_Right);
}

template<class _Ty1,
         class _Ty2> inline
constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left,
                const pair<_Ty1, _Ty2>& _Right)
{       // test for pair equality
  return _Left.first == _Right.first && _Left.second == _Right.second;
}

template<class _Ty1,
         class _Ty2> inline
constexpr bool operator!=(const pair<_Ty1, _Ty2>& _Left,
                const pair<_Ty1, _Ty2>& _Right)
{       // test for pair inequality
  return !(_Left == _Right);
}

template<class _Ty1,
         class _Ty2> inline
constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left,
               const pair<_Ty1, _Ty2>& _Right)
{       // test if _Left < _Right for pairs
  return   _Left.first < _Right.first
        || (!(_Right.first < _Left.first) && _Left.second < _Right.second);
}

template<class _Ty1,
         class _Ty2> inline
constexpr bool operator>(const pair<_Ty1, _Ty2>& _Left,
               const pair<_Ty1, _Ty2>& _Right)
{       // test if _Left > _Right for pairs
  return _Right < _Left;
}

template<class _Ty1,
         class _Ty2> inline
constexpr bool operator<=(const pair<_Ty1, _Ty2>& _Left,
                const pair<_Ty1, _Ty2>& _Right)
{       // test if _Left <= _Right for pairs
  return !(_Right < _Left);
}

template<class _Ty1,
         class _Ty2> inline
constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left,
                const pair<_Ty1, _Ty2>& _Right)
{       // test if _Left >= _Right for pairs
  return !(_Left < _Right);
}

// TEMPLATE FUNCTION make_pair
template<class _Ty1,
         class _Ty2> inline
constexpr pair<typename _Unrefwrap<_Ty1>::type,
               typename _Unrefwrap<_Ty2>::type>
make_pair(_Ty1&& _Val1, _Ty2&& _Val2)
{       // return pair composed from arguments
  typedef pair<typename _Unrefwrap<_Ty1>::type,
               typename _Unrefwrap<_Ty2>::type> _Mytype;
  return _Mytype(std::forward<_Ty1>(_Val1), std::forward<_Ty2>(_Val2));
}

// TEMPLATE OPERATORS
namespace rel_ops
{       // nested namespace to hide relational operators from std
  template<class _Ty> inline
  bool operator!=(const _Ty& _Left, const _Ty& _Right)
  {       // test for inequality, in terms of equality
    return !(_Left == _Right);
  }

  template<class _Ty> inline
  bool operator>(const _Ty& _Left, const _Ty& _Right)
  {       // test if _Left > _Right, in terms of operator<
    return _Right < _Left;
  }

  template<class _Ty> inline
  bool operator<=(const _Ty& _Left, const _Ty& _Right)
  {       // test if _Left <= _Right, in terms of operator<
    return !(_Right < _Left);
  }

  template<class _Ty> inline
  bool operator>=(const _Ty& _Left, const _Ty& _Right)
  {       // test if _Left >= _Right, in terms of operator<
    return !(_Left < _Right);
  }
} // namespace rel_ops

} /* namespace std */

namespace std {

template<class _Ty,
         size_t _Size>
class array;

// TEMPLATE STRUCT tuple_size
template<class _Tuple>
struct tuple_size
{       // size of non-tuple
  _STATIC_ASSERT2(_Always_false<_Tuple>::value,
                  "The C++ Standard doesn't define tuple_size for this type.");
};

template<class _Ty,
         size_t _Size>
struct tuple_size<array<_Ty, _Size> >
  : integral_constant<size_t, _Size>
{	// struct to determine number of elements in array
};

template<class _Ty1,
         class _Ty2>
struct tuple_size<pair<_Ty1, _Ty2> >
  : integral_constant<size_t, 2>
{       // size of pair
};

template<class... _Types>
struct tuple_size<tuple<_Types...> >
  : integral_constant<size_t, sizeof...(_Types)>
{       // size of tuple
};

template<class _Tuple>
struct tuple_size<const _Tuple>
  : tuple_size<_Tuple>
{	// size of const tuple
};

template<class _Tuple>
struct tuple_size<volatile _Tuple>
  : tuple_size<_Tuple>
{	// size of volatile tuple
};

template<class _Tuple>
struct tuple_size<const volatile _Tuple>
  : tuple_size<_Tuple>
{	// size of const volatile tuple
};

	// CLASS tuple_element (find element by index)
template<size_t _Index,
         class _Tuple>
struct tuple_element
{	// struct to enforce bounds checking
  _STATIC_ASSERT2(_Always_false<_Tuple>::value,
                  "tuple_element index out of bounds");
};

template<size_t _Idx,
         class _Ty,
         size_t _Size>
struct tuple_element<_Idx, array<_Ty, _Size> >
{	// struct to determine type of element _Idx in array
  tuple_element()
  {	// default construct
    _STATIC_ASSERT2(_Idx < _Size, "array index out of bounds");
  }

  typedef _Ty type;
};

template<class _Ty1,
         class _Ty2>
struct tuple_element<0, pair<_Ty1, _Ty2> >
{	// struct to determine type of element 0 in pair
  typedef _Ty1 type;
};

template<class _Ty1,
         class _Ty2>
struct tuple_element<1, pair<_Ty1, _Ty2> >
{	// struct to determine type of element 1 in pair
  typedef _Ty2 type;
};

template<class _This,
         class... _Rest>
struct tuple_element<0, tuple<_This, _Rest...> >
{	// select first element
  typedef _This type;
  typedef tuple<_This, _Rest...> _Ttype;
};

template<size_t _Index,
         class _This,
         class... _Rest>
struct tuple_element<_Index, tuple<_This, _Rest...> >
  : public tuple_element<_Index - 1, tuple<_Rest...> >
{	// recursive tuple_element definition
};

template<size_t _Index,
         class _Tuple>
struct tuple_element<_Index, const _Tuple>
  : public tuple_element<_Index, _Tuple>
{	// tuple_element for const
  typedef tuple_element<_Index, _Tuple> _Mybase;
  typedef typename add_const<typename _Mybase::type>::type type;
};

template<size_t _Index,
         class _Tuple>
struct tuple_element<_Index, volatile _Tuple>
  : public tuple_element<_Index, _Tuple>
{	// tuple_element for volatile
  typedef tuple_element<_Index, _Tuple> _Mybase;
  typedef typename add_volatile<typename _Mybase::type>::type type;
};

template<size_t _Index,
         class _Tuple>
struct tuple_element<_Index, const volatile _Tuple>
  : public tuple_element<_Index, _Tuple>
{	// tuple_element for const volatile
  typedef tuple_element<_Index, _Tuple> _Mybase;
  typedef typename add_cv<typename _Mybase::type>::type type;
};

template<size_t _Index,
         class _Tuple>
using tuple_element_t = typename tuple_element<_Index, _Tuple>::type;
 

// TUPLE INTERFACE TO pair
template<class _Ret,
         class _Pair> inline
constexpr _Ret _Pair_get(_Pair& _Pr,
                         integral_constant<size_t, 0>) _NOEXCEPT
{	// get reference to element 0 in pair _Pr
  return _Pr.first;
}

template<class _Ret,
         class _Pair> inline
constexpr _Ret _Pair_get(_Pair& _Pr,
                         integral_constant<size_t, 1>) _NOEXCEPT
{	// get reference to element 1 in pair _Pr
  return _Pr.second;
}

template<size_t _Idx,
         class _Ty1,
         class _Ty2> inline
constexpr typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type&
get(pair<_Ty1, _Ty2>& _Pr) _NOEXCEPT
{	// get reference to element at _Idx in pair _Pr
  typedef typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type& _Rtype;
  return _Pair_get<_Rtype>(_Pr, integral_constant<size_t, _Idx>());
}

template<class _Ty1,
         class _Ty2> inline
constexpr _Ty1& get(pair<_Ty1, _Ty2>& _Pr) _NOEXCEPT
{	// get reference to element _Ty1 in pair _Pr
  return std::get<0>(_Pr);
}

template<class _Ty2,
         class _Ty1> inline
constexpr _Ty2& get(pair<_Ty1, _Ty2>& _Pr) _NOEXCEPT
{	// get reference to element _Ty2 in pair _Pr
  return std::get<1>(_Pr);
}

template<size_t _Idx,
         class _Ty1,
         class _Ty2> inline
constexpr const typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type&
get(const pair<_Ty1, _Ty2>& _Pr) _NOEXCEPT
{	// get const reference to element at _Idx in pair _Pr
  typedef const typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type& _Ctype;
  return _Pair_get<_Ctype>(_Pr, integral_constant<size_t, _Idx>());
}

template<class _Ty1,
         class _Ty2> inline
constexpr const _Ty1& get(const pair<_Ty1, _Ty2>& _Pr) _NOEXCEPT
{	// get const reference to element _Ty1 in pair _Pr
  return std::get<0>(_Pr);
}

template<class _Ty2,
         class _Ty1> inline
constexpr const _Ty2& get(const pair<_Ty1, _Ty2>& _Pr) _NOEXCEPT
{	// get const reference to element _Ty2 in pair _Pr
  return std::get<1>(_Pr);
}

template<size_t _Idx,
         class _Ty1,
         class _Ty2> inline
constexpr typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type&&
get(pair<_Ty1, _Ty2>&& _Pr) _NOEXCEPT
{	// get rvalue reference to element at _Idx in pair _Pr
  typedef typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type&& _RRtype;
  return std::forward<_RRtype>(std::get<_Idx>(_Pr));
}

template<class _Ty1,
         class _Ty2> inline
constexpr _Ty1&& get(pair<_Ty1, _Ty2>&& _Pr) _NOEXCEPT
{	// get rvalue reference to element _Ty1 in pair _Pr
  return std::get<0>(std::move(_Pr));
}

template<class _Ty2,
         class _Ty1> inline
constexpr _Ty2&& get(pair<_Ty1, _Ty2>&& _Pr) _NOEXCEPT
{	// get rvalue reference to element _Ty2 in pair _Pr
  return std::get<1>(std::move(_Pr));
}

// TEMPLATE FUNCTION exchange

template<class _Ty,
         class _Other = _Ty> inline
_Ty exchange(_Ty& _Val, _Other && _New_val)
{	// assign _New_val to _Val, return previous _Val
  _Ty _Old_val = std::move(_Val);
  _Val = std::forward<_Other>(_New_val);
  return _Old_val;
}

} /* namespace std */


#endif /* _UTILITY_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0576 */
