fork download
  1. // http://stackoverflow.com/questions/23480041/is-the-member-field-order-of-a-class-stable
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <stddef.h>
  5.  
  6. struct Pair {
  7. int _data[2]; // _data[0] and _data[1] are consecutive,
  8. // and _data[0] is at offset 0 (&Pair == &_data[0])
  9. int _unused[6]; // simulate the compiler inserted some padding here
  10. int first() { return _data[0]; }
  11. int second() { return _data[1]; }
  12. int & operator[] ( size_t x ) { return _data[x]; }
  13. friend inline bool operator< ( const Pair & lhs, const Pair & rhs ) {
  14. return lhs._data[0] < rhs._data[0];
  15. }
  16. // it is unlikely that the compiler will add any padding to a struct
  17. // Pair, so sizeof(Pair) == sizeof(_data)
  18. // however, the standard doesn't preclude it, so we define our own
  19. // copy constructor and assignment operator to ensure that nothing
  20. // extraneous is stored
  21. Pair( const Pair& other ) {
  22. _data[0] = other._data[0];
  23. _data[1] = other._data[1];
  24. }
  25. const Pair& operator=( const Pair& other ) {
  26. _data[0] = other._data[0];
  27. _data[1] = other._data[1];
  28. return *this;
  29. }
  30. };
  31.  
  32. struct Pairs {
  33. int* _data;
  34. size_t _size;
  35. Pairs( int data[], size_t size ) : _data(data), _size(size) {}
  36. Pair & operator[] ( size_t x ) const {
  37. return *reinterpret_cast< Pair * >( _data + 2 * x );
  38. }
  39. class rai
  40. : public std::iterator<std::random_access_iterator_tag, Pair>
  41. {
  42. int * _p;
  43. size_t _size;
  44. size_t _x;
  45. public:
  46. rai() : _p(NULL), _size(0), _x(0) {}
  47. rai( int* data, size_t size )
  48. : _p(data), _size(size), _x(0) {}
  49. friend inline bool operator== (const rai& lhs, const rai& rhs) {
  50. return lhs._p == rhs._p && lhs._x == rhs._x;
  51. }
  52. friend inline bool operator!= (const rai& lhs, const rai& rhs) {
  53. return lhs._p != rhs._p || lhs._x != rhs._x;
  54. }
  55. Pair& operator* () const {
  56. return *reinterpret_cast< Pair * >( _p + 2 * _x );
  57. }
  58. rai& operator+=( ptrdiff_t n ) {
  59. _x += n;
  60. if (_x >= _size) { _x = _size = 0; _p = NULL; }
  61. return *this;
  62. }
  63. rai& operator-=( ptrdiff_t n ) {
  64. if (n > _x) _x = 0;
  65. else _x -= n;
  66. return *this;
  67. }
  68. friend inline rai operator+ ( rai lhs, const ptrdiff_t n ) {
  69. return lhs += n;
  70. }
  71. friend inline rai operator- ( rai lhs, const ptrdiff_t n ) {
  72. return lhs -= n;
  73. }
  74. friend inline bool operator< ( const rai & lhs, const rai & rhs ) {
  75. return *lhs < *rhs;
  76. }
  77. rai& operator++ () { return *this += 1; }
  78. rai& operator-- () { return *this -= 1; }
  79. friend inline ptrdiff_t operator-(const rai& lhs, const rai& rhs) {
  80. return lhs._p == NULL
  81. ? (rhs._p == NULL ? 0 : rhs._size - rhs._x)
  82. : lhs._x - rhs._x;
  83. }
  84. };
  85. inline rai begin() { return rai(_data,_size); }
  86. static inline const rai end() { return rai(); }
  87. };
  88.  
  89. int main() {
  90. int N=5;
  91. int data[10]= {1,2,7,8,13,14,10,11,4,5};
  92. Pairs pairs( data, N );
  93.  
  94. std::cout << "unsorted" << std::endl;
  95. for(int i=0; i<N; ++i)
  96. std::cout << i << ": (" << pairs[i].first() << ", "
  97. << pairs[i].second() << ")" << std::endl;
  98.  
  99. std::sort(pairs.begin(), pairs.end());
  100.  
  101. std::cout << "sorted" << std::endl;
  102. for(int i=0; i<N; ++i)
  103. std::cout << i
  104. << ": (" << pairs[i][0] // same as pairs[i].first()
  105. << ", " << pairs[i][1] // same as pairs[i].second()
  106. << ")" << std::endl;
  107.  
  108. return 0;
  109. }
  110.  
Success #stdin #stdout 0s 3344KB
stdin
Standard input is empty
stdout
unsorted
0: (1, 2)
1: (7, 8)
2: (13, 14)
3: (10, 11)
4: (4, 5)
sorted
0: (1, 2)
1: (4, 5)
2: (7, 8)
3: (10, 11)
4: (13, 14)