Advertisement
Guest User

Untitled

a guest
Feb 24th, 2017
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.35 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <cstdint>
  4. #include <type_traits>
  5. #include <utility>
  6.  
  7. namespace {
  8.  
  9. template <bool Signed>
  10. using minint = std::conditional_t<Signed, int8_t, uint8_t>;
  11. template <bool Signed>
  12. using maxint = std::conditional_t<Signed, intmax_t, uintmax_t>;
  13.  
  14. template <class T, class U>
  15. constexpr T combine() noexcept {
  16. return 0;
  17. }
  18. template <class T, class U>
  19. constexpr T combine(U x) noexcept {
  20. return x & static_cast<U>(~0);
  21. }
  22. template <class T, class U, class... Arg>
  23. constexpr T combine(U x, Arg... args) noexcept {
  24. return (combine<T, U>(x) << (sizeof...(args) * sizeof(U) * 8))
  25. | combine<T, U>(args...);
  26. }
  27.  
  28. } // namespace
  29.  
  30. template <std::size_t N, bool Signed = false>
  31. class ChainInt {
  32. using elem_type = minint<Signed>;
  33. using max_type = maxint<Signed>;
  34. static_assert(N > 0, "Cannot chain void integer");
  35. static_assert(N <= sizeof(max_type), "Chained integer too large");
  36.  
  37. elem_type *data_[N];
  38. max_type x_;
  39.  
  40. public:
  41. template <class... Arg>
  42. constexpr ChainInt(Arg&... args) noexcept :
  43. data_ {&args...}, x_(combine<max_type, elem_type>(args...)) { }
  44. ~ChainInt() noexcept = default;
  45.  
  46. constexpr operator max_type() const noexcept {
  47. return x_;
  48. }
  49. constexpr elem_type &operator[](std::size_t n) noexcept {
  50. return *data_[n];
  51. }
  52. constexpr const elem_type &operator[](std::size_t n) const noexcept {
  53. return *data_[n];
  54. }
  55.  
  56. constexpr ChainInt &operator=(const ChainInt &other) noexcept {
  57. return operator=(static_cast<const max_type&>(other));
  58. }
  59. #define ASSIGN(FN) \
  60. ChainInt &operator FN(const max_type &other) noexcept { \
  61. x_ FN other; update(); return *this; }
  62. ASSIGN(=)
  63. ASSIGN(+=)
  64. ASSIGN(-=)
  65. ASSIGN(*=)
  66. ASSIGN(/=)
  67. ASSIGN(%=)
  68. ASSIGN(<<=)
  69. ASSIGN(>>=)
  70. ASSIGN(&=)
  71. ASSIGN(|=)
  72. ASSIGN(^=)
  73. #undef ASSIGN
  74.  
  75. #define UNARY(FN) \
  76. ChainInt &operator FN() noexcept { FN x_; update(); return *this; } \
  77. max_type operator FN(int) noexcept { auto v = x_; operator FN(); return v; }
  78. UNARY(++)
  79. UNARY(--)
  80. #undef UNARY
  81.  
  82. private:
  83. constexpr void update() noexcept {
  84. x_ &= static_cast<max_type>(-1) >> (8 * (8 - N));
  85. auto v = x_;
  86. for (std::size_t i = 0; i < N; ++i) {
  87. *data_[N - i - 1] = v;
  88. v >>= sizeof(elem_type) * 8;
  89. }
  90. }
  91. };
  92.  
  93. namespace {
  94.  
  95. template <class... Arg> struct all_lv_refs;
  96. template <class T> struct all_lv_refs<T> :
  97. std::is_lvalue_reference<T> { };
  98. template <class T, class... Arg> struct all_lv_refs<T, Arg...> :
  99. std::conditional_t<!std::is_lvalue_reference<T>::value,
  100. std::false_type, all_lv_refs<Arg...>> { };
  101.  
  102. template <bool B, class T, class... Arg> struct chain_impl;
  103. template <class T, class... Arg>
  104. struct chain_impl<false, T, Arg...> {
  105. constexpr auto operator()(T x, Arg... args) noexcept {
  106. using T2 = std::decay_t<T>;
  107. return combine<maxint<std::is_signed<T>::value>, T2>(
  108. x, static_cast<T2>(args)...);
  109. }
  110. };
  111. template <class T, class... Arg>
  112. struct chain_impl<true, T, Arg...> {
  113. constexpr auto operator()(T x, Arg... args) noexcept {
  114. return ChainInt<1 + sizeof...(Arg), std::is_signed<T>::value>(
  115. x, args...);
  116. }
  117. };
  118.  
  119. } // namespace
  120.  
  121. template <class T, class... Arg>
  122. constexpr auto chain(T &&x, Arg&&... args) noexcept {
  123. return chain_impl<all_lv_refs<T, Arg...>::value, T, Arg...>()(x, args...);
  124. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement