fork download
  1. #include <iostream>
  2.  
  3. struct X
  4. {
  5. X() : id(instances++)
  6. {
  7. std::cout << "X" << id << ": construct\n";
  8. }
  9.  
  10. X(X const& rhs) : id(instances++)
  11. {
  12. std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **copy**\n";
  13. ++copies;
  14. }
  15.  
  16. X(X&& rhs) : id(instances++)
  17. {
  18. std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **move**\n";
  19. ++moves;
  20. }
  21.  
  22. // This particular test doesn't exercise assignment, but for
  23. // completeness:
  24. X& operator=(X const& rhs)
  25. {
  26. std::cout << "X" << id << ": <- " << "X" << rhs.id << ": copy-assign\n";
  27. }
  28.  
  29. X& operator=(X&& rhs)
  30. {
  31. std::cout << "X" << id << ": <- " << "X" << rhs.id << ": move-assign\n";
  32. }
  33.  
  34. ~X() { std::cout << "X" << id << ": destroy\n"; }
  35.  
  36. X& operator+=( const X& rhs ) {
  37. std::cout << "X" << id << ": += " << "X" << rhs.id << ": add-assign\n";
  38. return *this;
  39. }
  40.  
  41. unsigned id;
  42.  
  43. static unsigned copies;
  44. static unsigned moves;
  45. static unsigned instances;
  46. };
  47.  
  48. X operator+( X lhs, const X& rhs ) {
  49. std::cout << "X" << lhs.id << ": + " << "X" << rhs.id << ": add\n";
  50. lhs += rhs;
  51. return lhs;
  52. }
  53.  
  54. unsigned X::copies = 0;
  55. unsigned X::moves = 0;
  56. unsigned X::instances = 0;
  57.  
  58. #define CHECK_COPIES( stmt, min, max_copies, max_moves, comment ) \
  59. { \
  60.   unsigned const old_copies = X::copies; \
  61.   unsigned const old_moves = X::moves; \
  62.   \
  63.   std::cout << "\n" comment "\n" #stmt "\n===========\n"; \
  64.   { \
  65.   stmt; \
  66.   } \
  67.   unsigned const n = X::copies - old_copies; \
  68.   unsigned const m = X::moves - old_moves; \
  69.   unsigned const t = n+m; \
  70.   if (t < min) \
  71.   std::cout << "*** min is too high or compiler is buggy ***\n"; \
  72.   if (n > max_copies) \
  73.   std::cout << "*** max_copies is too low or compiler is buggy ***\n";\
  74.   if (m > max_moves) \
  75.   std::cout << "*** max_moves is too low or compiler is buggy ***\n"; \
  76.   \
  77.   \
  78.   std::cout << "-----------\n" \
  79.   << n << "/" << max_copies \
  80.   << " possible copies made\n" \
  81.   << m << "/" << max_moves \
  82.   << " possible moves made\n" \
  83.   << max_copies - t << "/" << max_copies - min \
  84.   << " possible elisions performed\n\n"; \
  85.   \
  86.   if (t > min) \
  87.   std::cout << "*** " << t - min \
  88.   << " possible elisions missed! ***\n"; \
  89. }
  90.  
  91. X lvalue_;
  92. X& lvalue()
  93. {
  94. return lvalue_;
  95. }
  96. typedef X rvalue;
  97.  
  98. int main()
  99. {
  100. CHECK_COPIES( lvalue() + lvalue(), 1, 2, 1, "lvalue + lvalue" );
  101. CHECK_COPIES( rvalue() + lvalue(), 0, 2, 2, "rvalue + lvalue" );
  102. CHECK_COPIES( lvalue() + rvalue(), 1, 2, 1, "lvalue + rvalue" );
  103. }
Success #stdin #stdout 0s 2856KB
stdin
Standard input is empty
stdout
X0: construct

lvalue + lvalue
lvalue() + lvalue()
===========
X1: <- X0: **copy**
X1: +  X0: add
X1: += X0: add-assign
X2: <- X1: **move**
X2: destroy
X1: destroy
-----------
1/2 possible copies made
1/1 possible moves made
0/1 possible elisions performed

*** 1 possible elisions missed! ***

rvalue + lvalue
rvalue() + lvalue()
===========
X3: construct
X3: +  X0: add
X3: += X0: add-assign
X4: <- X3: **move**
X4: destroy
X3: destroy
-----------
0/2 possible copies made
1/2 possible moves made
1/2 possible elisions performed

*** 1 possible elisions missed! ***

lvalue + rvalue
lvalue() + rvalue()
===========
X5: construct
X6: <- X0: **copy**
X6: +  X5: add
X6: += X5: add-assign
X7: <- X6: **move**
X7: destroy
X6: destroy
X5: destroy
-----------
1/2 possible copies made
1/1 possible moves made
0/1 possible elisions performed

*** 1 possible elisions missed! ***
X0: destroy