fork(1) download
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <iterator>
  5. #include <functional>
  6. using namespace std;
  7.  
  8. // the name is misleading and shows only what I
  9. // intended when starting to write this code. Now
  10. // a name like weird_thing would probably be more
  11. // appropriate.
  12. template <class T>
  13. class copyable_ref {
  14. public:
  15. copyable_ref(T& ref) noexcept
  16. : _ptr(std::addressof(ref)), _copied(false) {}
  17. copyable_ref(T&&) = delete;
  18. copyable_ref(const copyable_ref& x) noexcept
  19. : _ptr (new int(*x._ptr)), _copied (true) {
  20. cout << "copied " << x._ptr << ":" << *x._ptr << " to " << _ptr << endl;
  21. }
  22. ~copyable_ref() {
  23. if (_copied) {
  24. cout << "freed " << _ptr << ":" << *_ptr << endl;
  25. delete _ptr;
  26. }
  27. }
  28.  
  29. copyable_ref& operator=(const copyable_ref& x) noexcept {
  30. cout << _ptr << ":" << *_ptr << " overwritten with " << x._ptr << ":" << *x._ptr << endl;
  31. *_ptr = *x._ptr;
  32. // _ptr = x._ptr;
  33. }
  34.  
  35. operator T& () const noexcept { return *_ptr; }
  36. T& get() const noexcept { return *_ptr; }
  37.  
  38. // unused by sort ... :/
  39. void swap(copyable_ref & x) {
  40. cout << "swap member" << endl;
  41. }
  42.  
  43. private:
  44. T* _ptr;
  45. bool _copied;
  46. };
  47.  
  48. // I couldn't convince std::sort to use this.
  49. // That's why the copy constructor of the class
  50. // needs to be so weird.
  51. template<typename T>
  52. void swap(copyable_ref<T> & lhs, copyable_ref<T> & rhs) {
  53. cout << "swap" << endl;
  54. }
  55.  
  56.  
  57. int main(int, char **) {
  58. vector<int> input {1,2,3,4,5,6,7,8,9};
  59.  
  60. // Vector with the references, reserving space isn't
  61. // a performance thing, it's absolutely necessary to
  62. // prevent the vector from copying elements.
  63. vector<copyable_ref<int>> sorted;
  64. sorted.reserve(input.size());
  65. for (auto & e : input) {
  66. if (e % 2 != 0) {
  67. // emplace to prevent calling the copy constructor.
  68. // We need this with references to the real items,
  69. // and not to heap allocated copies of them.
  70. sorted.emplace_back(e);
  71. }
  72. }
  73.  
  74. copy(begin(sorted), end(sorted),
  75. ostream_iterator<int>{cout, ", "});
  76. cout << endl;
  77.  
  78. // The actual sorting. This seems to contain code like
  79. // T t(a);
  80. // a = b;
  81. // b = t;
  82. // instead of using swap. This is the reason for the
  83. // strange copy constructor.
  84. sort(begin(sorted), end(sorted),
  85. greater<int>{});
  86.  
  87. copy(begin(sorted), end(sorted),
  88. ostream_iterator<int>{cout, ", "});
  89. cout << endl;
  90.  
  91. copy(begin(input), end(input),
  92. ostream_iterator<int>{cout, ", "});
  93. cout << endl;
  94. return 0;
  95. }
Success #stdin #stdout 0s 3468KB
stdin
Standard input is empty
stdout
1, 3, 5, 7, 9, 
copied 0x9456a18:3 to 0x9456a88
0x9456a18:3 overwritten with 0x9456a10:1
0x9456a10:1 overwritten with 0x9456a88:3
freed 0x9456a88:3
copied 0x9456a20:5 to 0x9456a88
0x9456a20:5 overwritten with 0x9456a18:1
0x9456a18:1 overwritten with 0x9456a10:3
0x9456a10:3 overwritten with 0x9456a88:5
freed 0x9456a88:5
copied 0x9456a28:7 to 0x9456a88
0x9456a28:7 overwritten with 0x9456a20:1
0x9456a20:1 overwritten with 0x9456a18:3
0x9456a18:3 overwritten with 0x9456a10:5
0x9456a10:5 overwritten with 0x9456a88:7
freed 0x9456a88:7
copied 0x9456a30:9 to 0x9456a88
0x9456a30:9 overwritten with 0x9456a28:1
0x9456a28:1 overwritten with 0x9456a20:3
0x9456a20:3 overwritten with 0x9456a18:5
0x9456a18:5 overwritten with 0x9456a10:7
0x9456a10:7 overwritten with 0x9456a88:9
freed 0x9456a88:9
9, 7, 5, 3, 1, 
9, 2, 7, 4, 5, 6, 3, 8, 1,