#ifndef UTILS2_HPP #define UTILS2_HPP #include "sanity.hpp" #include #include #include #include #include #ifdef __clang__ # define FALLTHROUGH [[clang::fallthrough]] #else # define FALLTHROUGH /* fallthrough */ #endif template struct earray { // no ctor/dtor and one public member variable for easy initialization T _data[size_t(max)]; T& operator[](E v) { return _data[size_t(v)]; } const T& operator[](E v) const { return _data[size_t(v)]; } T *begin() { return _data; } T *end() { return _data + size_t(max); } const T *begin() const { return _data; } const T *end() const { return _data + size_t(max); } friend bool operator == (const earray& l, const earray& r) { return std::equal(l.begin(), l.end(), r.begin()); } friend bool operator != (const earray& l, const earray& r) { return !(l == r); } }; template class eptr { T *_data; public: eptr(decltype(nullptr)=nullptr) : _data(nullptr) {} template eptr(earray& arr) : _data(arr._data) {} T& operator [](E v) { return _data[size_t(v)]; } explicit operator bool() { return _data; } bool operator not() { return not _data; } }; template class IteratorPair { It _b, _e; public: IteratorPair(It b, It e) : _b(b), _e(e) {} It begin() { return _b; } It end() { return _e; } }; template IteratorPair iterator_pair(It b, It e) { return {b, e}; } // std::underlying_type isn't supported until gcc 4.7 // this is a poor man's emulation template struct underlying_type { static_assert(std::is_enum::value, "Only enums have underlying type!"); typedef typename std::conditional< std::is_signed::value, typename std::make_signed::type, typename std::make_unsigned::type >::type type; }; template::value> struct remove_enum { typedef E type; }; template struct remove_enum { typedef typename underlying_type::type type; }; #define ENUM_BITWISE_OPERATORS(E) \ inline \ E operator & (E l, E r) \ { \ typedef underlying_type::type U; \ return E(U(l) & U(r)); \ } \ inline \ E operator | (E l, E r) \ { \ typedef underlying_type::type U; \ return E(U(l) | U(r)); \ } \ inline \ E operator ^ (E l, E r) \ { \ typedef underlying_type::type U; \ return E(U(l) ^ U(r)); \ } \ inline \ E& operator &= (E& l, E r) \ { \ return l = l & r; \ } \ inline \ E& operator |= (E& l, E r) \ { \ return l = l | r; \ } \ inline \ E& operator ^= (E& l, E r) \ { \ return l = l ^ r; \ } \ inline \ E operator ~ (E r) \ { \ return E(-1) ^ r; \ } template class EnumValueIterator { typedef typename underlying_type::type U; E value; public: EnumValueIterator(E v) : value(v) {} E operator *() { return value; } EnumValueIterator& operator++ () { value = E(U(value) + 1); return *this; } EnumValueIterator& operator-- () { value = E(U(value) - 1); return *this; } friend bool operator == (EnumValueIterator l, EnumValueIterator r) { return l.value == r.value; } friend bool operator != (EnumValueIterator l, EnumValueIterator r) { return !(l == r); } }; template IteratorPair> erange(E b, E e) { return {b, e}; } namespace ph = std::placeholders; template typename std::common_type::type min(A a, B b) { return a < b ? a : b; } template typename std::common_type::type max(A a, B b) { return b < a ? a : b; } template struct is_array_of_unknown_bound : std::is_same::type[]> {}; template, class... A> typename std::enable_if::value, std::unique_ptr>::type make_unique(A&&... a) { return std::unique_ptr(new T(a...)); } template> typename std::enable_if::value, std::unique_ptr>::type make_unique(size_t sz) { typedef typename std::remove_extent::type E; return std::unique_ptr(new E[sz]()); } #endif // UTILS2_HPP