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+( const X& lhs, const X& rhs ) {
  49. std::cout << "X" << lhs.id << ": + " << "X" << rhs.id << ": add\n";
  50. X rv = lhs;
  51. rv += rhs;
  52. return rv;
  53. }
  54.  
  55. unsigned X::copies = 0;
  56. unsigned X::moves = 0;
  57. unsigned X::instances = 0;
  58.  
  59. #define CHECK_COPIES( stmt, min, max_copies, max_moves, comment ) \
  60. { \
  61.   unsigned const old_copies = X::copies; \
  62.   unsigned const old_moves = X::moves; \
  63.   \
  64.   std::cout << "\n" comment "\n" #stmt "\n===========\n"; \
  65.   { \
  66.   stmt; \
  67.   } \
  68.   unsigned const n = X::copies - old_copies; \
  69.   unsigned const m = X::moves - old_moves; \
  70.   unsigned const t = n+m; \
  71.   if (t < min) \
  72.   std::cout << "*** min is too high or compiler is buggy ***\n"; \
  73.   if (n > max_copies) \
  74.   std::cout << "*** max_copies is too low or compiler is buggy ***\n";\
  75.   if (m > max_moves) \
  76.   std::cout << "*** max_moves is too low or compiler is buggy ***\n"; \
  77.   \
  78.   \
  79.   std::cout << "-----------\n" \
  80.   << n << "/" << max_copies \
  81.   << " possible copies made\n" \
  82.   << m << "/" << max_moves \
  83.   << " possible moves made\n" \
  84.   << max_copies - t << "/" << max_copies - min \
  85.   << " possible elisions performed\n\n"; \
  86.   \
  87.   if (t > min) \
  88.   std::cout << "*** " << t - min \
  89.   << " possible elisions missed! ***\n"; \
  90. }
  91.  
  92. X lvalue_;
  93. X& lvalue()
  94. {
  95. return lvalue_;
  96. }
  97. typedef X rvalue;
  98.  
  99. int main()
  100. {
  101. CHECK_COPIES( lvalue() + lvalue(), 1, 2, 1, "lvalue + lvalue" );
  102. CHECK_COPIES( rvalue() + lvalue(), 1, 2, 1, "rvalue + lvalue" );
  103. CHECK_COPIES( lvalue() + rvalue(), 1, 2, 1, "lvalue + rvalue" );
  104. }
  105.  
Success #stdin #stdout 0s 2856KB
stdin
Standard input is empty
stdout
X0: construct

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


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


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

X0: destroy