fork download
  1. #include <iostream>
  2. #include <type_traits>
  3.  
  4. struct Data {
  5. Data() { std::cout << " constructor\n";}
  6. Data(const Data& data) { std::cout << " copy constructor\n";}
  7. Data(Data&& data) { std::cout << " move constructor\n";}
  8. };
  9.  
  10. struct DataWrapperWithMove {
  11. Data data_;
  12. DataWrapperWithMove(Data&& data) : data_(std::move(data)) { }
  13. };
  14.  
  15. struct DataWrapperByValue {
  16. Data data_;
  17. DataWrapperByValue(Data data) : data_(std::move(data)) { }
  18. };
  19.  
  20. struct DataWrapperByMoveOrCopy {
  21. Data data_;
  22. template<typename T,
  23. typename = typename std::enable_if<
  24. std::is_same<typename std::decay<T>::type, Data>::value
  25. >::type
  26. >
  27. DataWrapperByMoveOrCopy(T&& data) : data_(std::forward<T>(data)) { }
  28. };
  29.  
  30. struct Foo {
  31. Foo() { std::cout << " constructor\n";}
  32. Foo(const Foo& data) { std::cout << " copy constructor\n";}
  33. Foo(Foo&& data) { std::cout << " move constructor\n";}
  34. };
  35.  
  36. struct Bar {
  37. Bar() { std::cout << " constructor\n";}
  38. Bar(const Bar& data) { std::cout << " copy constructor\n";}
  39. Bar(Bar&& data) { std::cout << " move constructor\n";}
  40. };
  41.  
  42. struct Baz {
  43. Baz() { std::cout << " constructor\n";}
  44. Baz(const Baz& data) { std::cout << " copy constructor\n";}
  45. Baz(Baz&& data) { std::cout << " move constructor\n";}
  46. };
  47.  
  48. struct CompositeWrapperByMoveOrCopy {
  49. Data data_;
  50. Foo foo_;
  51. Bar bar_;
  52. Baz baz_;
  53. template<typename T, typename U, typename V, typename W,
  54. typename = typename std::enable_if<
  55. std::is_same<typename std::decay<T>::type, Data>::value &&
  56. std::is_same<typename std::decay<U>::type, Foo>::value &&
  57. std::is_same<typename std::decay<V>::type, Bar>::value &&
  58. std::is_same<typename std::decay<W>::type, Baz>::value
  59. >::type
  60. >
  61. CompositeWrapperByMoveOrCopy(T&& data, U&& foo, V&& bar, W&& baz) :
  62. data_{ std::forward<T>(data) },
  63. foo_{ std::forward<U>(foo) },
  64. bar_{ std::forward<V>(bar) },
  65. baz_{ std::forward<W>(baz) } { }
  66. };
  67.  
  68. Data function_returning_data() {
  69. return Data();
  70. }
  71.  
  72. int main() {
  73. std::cout << "1. DataWrapperWithMove:\n";
  74. Data d1;
  75. DataWrapperWithMove a1(std::move(d1));
  76.  
  77. std::cout << "2. DataWrapperByValue:\n";
  78. Data d2;
  79. DataWrapperByValue a2(std::move(d2));
  80.  
  81. std::cout << "3. DataWrapperByMoveOrCopy:\n";
  82. Data d3;
  83. DataWrapperByMoveOrCopy a3(std::move(d3));
  84.  
  85. std::cout << "4. DataWrapperByMoveOrCopy with l-value:\n";
  86. Data d4;
  87. DataWrapperByMoveOrCopy a4(d4);
  88.  
  89. std::cout << "5. RVO:\n";
  90. DataWrapperByValue a5(function_returning_data());
  91.  
  92. std::cout << "6. CompositeWrapperByMoveOrCopy with l-value:\n";
  93. Data d6;
  94. Foo f;
  95. Bar b;
  96. Baz z;
  97. int i;
  98. CompositeWrapperByMoveOrCopy a6(d6, std::move(f), b, std::move(z)); //works
  99. //CompositeWrapperByMoveOrCopy a7(d6, std::move(f), z, std::move(b)); //SFINAE kills it
  100. //CompositeWrapperByMoveOrCopy a8(d6, std::move(f), b, i); //SFINAE kills it
  101. }
Success #stdin #stdout 0s 3296KB
stdin
Standard input is empty
stdout
1. DataWrapperWithMove:
  constructor
  move constructor
2. DataWrapperByValue:
  constructor
  move constructor
  move constructor
3. DataWrapperByMoveOrCopy:
  constructor
  move constructor
4. DataWrapperByMoveOrCopy with l-value:
  constructor
  copy constructor
5. RVO:
  constructor
  move constructor
6. CompositeWrapperByMoveOrCopy with l-value:
  constructor
  constructor
  constructor
  constructor
  copy constructor
  move constructor
  copy constructor
  move constructor