/* Utilities for OctaSTD. * * This file is part of OctaSTD. See COPYING.md for futher information. */ #ifndef OCTA_UTILITY_H #define OCTA_UTILITY_H #include #include "octa/type_traits.h" namespace octa { /* move */ template static inline constexpr RemoveReference<_T> &&move(_T &&__v) { return static_cast &&>(__v); } /* forward */ template static inline constexpr _T &&forward(RemoveReference<_T> &__v) { return static_cast<_T &&>(__v); } template static inline constexpr _T &&forward(RemoveReference<_T> &&__v) { return static_cast<_T &&>(__v); } /* exchange */ template _T exchange(_T &__v, _U &&__nv) { _T __old = move(__v); __v = forward<_U>(__nv); return __old; } /* declval */ template AddRvalueReference<_T> declval(); /* swap */ template struct __OctaSwapTest { template struct __Test {}; template static char __test(__Test<_U, &_U::swap> *); template static int __test(...); static constexpr bool value = (sizeof(__test<_T>(0)) == sizeof(char)); }; template inline void __octa_swap(_T &__a, _T &__b, EnableIf< __OctaSwapTest<_T>::value, bool > = true) { __a.swap(__b); } template inline void __octa_swap(_T &__a, _T &__b, EnableIf< !__OctaSwapTest<_T>::value, bool > = true) { _T __c(octa::move(__a)); __a = octa::move(__b); __b = octa::move(__c); } template void swap(_T &__a, _T &__b) { __octa_swap(__a, __b); } template void swap(_T (&__a)[_N], _T (&__b)[_N]) { for (size_t __i = 0; __i < _N; ++__i) { octa::swap(__a[__i], __b[__i]); } } /* pair */ template struct Pair { _T first; _U second; Pair() = default; ~Pair() = default; Pair(const Pair &) = default; Pair(Pair &&) = default; Pair(const _T &__x, const _U &__y): first(__x), second(__y) {} template Pair(_TT &&__x, _UU &&__y): first(octa::forward<_TT>(__x)), second(octa::forward<_UU>(__y)) {} template Pair(const Pair<_TT, _UU> &__v): first(__v.first), second(__v.second) {} template Pair(Pair<_TT, _UU> &&__v): first(octa::move(__v.first)), second(octa::move(__v.second)) {} Pair &operator=(const Pair &__v) { first = __v.first; second = __v.second; return *this; } template Pair &operator=(const Pair<_TT, _UU> &__v) { first = __v.first; second = __v.second; return *this; } Pair &operator=(Pair &&__v) { first = octa::move(__v.first); second = octa::move(__v.second); return *this; } template Pair &operator=(Pair<_TT, _UU> &&__v) { first = octa::forward<_TT>(__v.first); second = octa::forward<_UU>(__v.second); return *this; } void swap(Pair &__v) { octa::swap(first, __v.first); octa::swap(second, __v.second); } }; template struct ReferenceWrapper; template struct __OctaMakePairRetBase { typedef _T Type; }; template struct __OctaMakePairRetBase> { typedef _T &Type; }; template struct __OctaMakePairRet { typedef typename __OctaMakePairRetBase>::Type Type; }; template Pair::Type, typename __OctaMakePairRet<_U>::Type > make_pair(_T &&__a, _U &&__b) { return Pair::Type, typename __OctaMakePairRet<_U>::Type >(forward<_T>(__a), forward<_U>(__b));; } } #endif