fork download
  1. #include <utility>
  2. #include <iostream>
  3. #include <functional>
  4.  
  5. using namespace std;
  6.  
  7. class Function
  8. {
  9. struct Concept {
  10. typedef Concept * (*cloneFunType)(const Concept *);
  11. cloneFunType m_cloneFun = nullptr;
  12.  
  13. virtual ~Concept() = default;
  14. };
  15.  
  16. template<typename F>
  17. struct Model final : Concept {
  18. static Concept* clone(const Concept *c) {
  19. return new Model(static_cast<const Model*>(c)->data);
  20. }
  21.  
  22. explicit Model(F &&f) : data(move(f)) {
  23. this->m_cloneFun = &Model::clone;
  24. }
  25.  
  26. explicit Model(const F &f) : data(f) {
  27. this->m_cloneFun = &Model::clone;
  28. }
  29.  
  30. F data;
  31. };
  32.  
  33. Concept* object;
  34.  
  35.  
  36. public:
  37. ~Function() {
  38. delete object;
  39. }
  40.  
  41.  
  42. template<typename F>
  43. explicit Function(F&& f)
  44. : object(new Model<typename remove_reference<F>::type>(forward<F>(f)))
  45. {}
  46.  
  47. Function(Function const& that)
  48. : object((*(that.object->m_cloneFun))(that.object))
  49. {}
  50.  
  51. Function(Function && that)
  52. : object(that.object)
  53. {
  54. that.object = nullptr;
  55. }
  56.  
  57. //...
  58. };
  59.  
  60. struct A {
  61. A() = default;
  62. A(const A&) {
  63. cout << "calling As copy constructor" << endl;
  64. }
  65. A(A&&) {
  66. cout << "calling As move constructor" << endl;
  67. }
  68.  
  69. };
  70.  
  71. struct B {
  72. B() = default;
  73. B(const B&) = delete;
  74. B(B&&) {
  75. cout << "calling Bs move constructor" << endl;
  76. }
  77.  
  78. };
  79.  
  80. int main(){
  81. auto fA = Function(A()); //at runtime, will only call move constructor.
  82. //auto fB = Function(B()); //will not compile.
  83.  
  84. cout << "is_copy_constructible<Function>::value: "
  85. << is_copy_constructible<Function>::value << endl;
  86.  
  87. cout << "is_copy_constructible<function<void()>>::value: "
  88. << is_copy_constructible<function<void()>>::value << endl;
  89. }
Success #stdin #stdout 0s 3428KB
stdin
Standard input is empty
stdout
calling As move constructor
is_copy_constructible<Function>::value: 1
is_copy_constructible<function<void()>>::value: 1