fork download
  1. #include <limits.h>
  2. #include <iostream>
  3. using namespace std;
  4.  
  5. template<size_t> struct ChooseImpl;
  6. template<> struct ChooseImpl<1> { typedef unsigned char type; };
  7. template<> struct ChooseImpl<2> { typedef uint16_t type; };
  8. template<> struct ChooseImpl<3> { typedef uint32_t type; };
  9. template<> struct ChooseImpl<4> { typedef uint32_t type; };
  10. template<> struct ChooseImpl<5> { typedef uint64_t type; };
  11. template<> struct ChooseImpl<6> { typedef uint64_t type; };
  12. template<> struct ChooseImpl<7> { typedef uint64_t type; };
  13. template<> struct ChooseImpl<8> { typedef uint64_t type; };
  14.  
  15. template<size_t N0, size_t... Ns>
  16. struct Max
  17. {
  18. static const size_t value = N0 >= Max<Ns...>::value ? N0 : Max<Ns...>::value;
  19. };
  20.  
  21. template<size_t N>
  22. struct Max<N>
  23. {
  24. static const size_t value = N;
  25. };
  26.  
  27. template<size_t W0, size_t... Ws>
  28. struct Choose
  29. {
  30. typedef typename ChooseImpl<(Max<W0, Ws...>::value + CHAR_BIT - 1) / CHAR_BIT>::type type;
  31. };
  32.  
  33. template<typename T, bool>
  34. struct AddSigned
  35. {
  36. typedef T type;
  37. };
  38.  
  39. template<typename T>
  40. struct AddSigned<T, true>
  41. {
  42. typedef typename make_signed<T>::type type;
  43. };
  44.  
  45. template<size_t W, bool S = false>
  46. struct Bitset
  47. {
  48. typedef typename AddSigned<typename Choose<W>::type, S>::type value_type;
  49.  
  50. value_type v : W;
  51. };
  52.  
  53. template<typename, typename, typename...> struct BitField;
  54.  
  55. template<size_t W0, size_t W1, bool S0, bool S1>
  56. struct BitField<Bitset<W0, S0>, Bitset<W1, S1>>
  57. {
  58. typedef typename Choose<W0, W1>::type value_type;
  59.  
  60. typename AddSigned<value_type, S0>::type v0 : W0;
  61. typename AddSigned<value_type, S1>::type v1 : W1;
  62. };
  63.  
  64. template<size_t W0, size_t W1, size_t W2, bool S0, bool S1, bool S2>
  65. struct BitField<Bitset<W0, S0>, Bitset<W1, S1>, Bitset<W2, S2>>
  66. {
  67. typedef typename Choose<W0, W1, W2>::type value_type;
  68.  
  69. typename AddSigned<value_type, S0>::type v0 : W0;
  70. typename AddSigned<value_type, S1>::type v1 : W1;
  71. typename AddSigned<value_type, S2>::type v2 : W2;
  72. };
  73.  
  74. template<size_t W0, size_t W1, size_t W2, size_t W3, bool S0, bool S1, bool S2, bool S3>
  75. struct BitField<Bitset<W0, S0>, Bitset<W1, S1>, Bitset<W2, S2>, Bitset<W3, S3>>
  76. {
  77. typedef typename Choose<W0, W1, W2, W3>::type value_type;
  78.  
  79. typename AddSigned<value_type, S0>::type v0 : W0;
  80. typename AddSigned<value_type, S1>::type v1 : W1;
  81. typename AddSigned<value_type, S2>::type v2 : W2;
  82. typename AddSigned<value_type, S3>::type v3 : W3;
  83. };
  84.  
  85. template<size_t W, bool S>
  86. typename Bitset<W, S>::value_type Get(Bitset<W, S> const &arg)
  87. {
  88. return arg.v;
  89. }
  90.  
  91. template<size_t W0, size_t W1, size_t... Ws, bool S0, bool S1, bool... Ss>
  92. BitField<Bitset<W0, S0>, Bitset<W1, S1>, Bitset<Ws, Ss>...> MakeBitField(Bitset<W0, S0> const &arg0, Bitset<W1, S1> const &arg1, Bitset<Ws, Ss> const &... args)
  93. {
  94. return{ Get(arg0), Get(arg1), Get(args)... };
  95. }
  96.  
  97. int main() {
  98. typedef Bitset<4> UInt4;
  99. typedef Bitset<10, true> Int10;
  100. UInt4 a = { 15 };
  101. Int10 b = { -1 };
  102. auto c = MakeBitField(UInt4{ 17 }, Int10{ 512 });
  103. cout << sizeof(a)
  104. << ' ' << (unsigned)a.v
  105. << ' ' << sizeof(b)
  106. << ' ' << b.v
  107. << ' ' << sizeof(c)
  108. << ' ' << c.v0
  109. << ' ' << c.v1
  110. << endl;
  111. return 0;
  112. }
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
1 15 2 -1 2 1 -512