fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <map>
  4. #include <functional>
  5. #include <memory>
  6. using namespace std;
  7.  
  8. class GenericData
  9. {
  10. public:
  11. virtual ~GenericData() {};
  12. };
  13.  
  14. class Data1 : public GenericData
  15. {
  16. public:
  17. virtual ~Data1() {};
  18. };
  19.  
  20. class Data2 : public GenericData
  21. {
  22. public:
  23. virtual ~Data2() {};
  24. };
  25.  
  26. class GenericComp
  27. {
  28. public:
  29. virtual ~GenericComp() {};
  30. vector<GenericData*> inputs;
  31. };
  32.  
  33. class Comp1 : public GenericComp
  34. {
  35. public:
  36. static bool compute(shared_ptr<Data1> const & input1, shared_ptr<Data1> const & input2) { cout << "Comp1::compute(Data1 input1, Data1 input2)" << (input2 ? "ok" : "null") << endl; return true; }
  37. static bool compute(shared_ptr<Data2> const & input1, shared_ptr<Data2> const & input2) { cout << "Comp1::compute(Data2 input1, Data2 input2)" << endl; return true; }
  38. static bool compute(shared_ptr<Data1> const & input1, shared_ptr<Data2> const & input2) { cout << "Comp1::compute(Data1 input1, Data2 input2)" << endl; return true; }
  39. };
  40.  
  41. class Comp2 : public GenericComp
  42. {
  43. public:
  44. static bool compute(shared_ptr<Data1> const & input1) { cout << "Comp2::compute(Data1 input1)" << endl; return true; }
  45. static bool compute(shared_ptr<Data2> const & input1) { cout << "Comp2::compute(Data2 input1)" << endl; return true; }
  46. };
  47.  
  48. // Arguments type to the function "interface"
  49. using Arguments = std::vector<shared_ptr<GenericData>> const &;
  50. // the interface
  51. using Function = std::function<bool (Arguments)>;
  52.  
  53. // Base case of packing a function.
  54. // If it's taking a vector and no more
  55. // arguments, then there's nothing left to
  56. // pack.
  57. template<std::size_t N, typename Fn>
  58. Function pack(Fn && fn)
  59. {
  60. return [fn = std::forward<decltype(fn)>(fn)] (Arguments arguments)
  61. {
  62. if (N != arguments.size())
  63. {
  64. throw std::string{"wrong number of arguments, expected "} +
  65. std::to_string(N) +
  66. std::string{" but got "} +
  67. std::to_string(arguments.size());
  68. }
  69. return fn(arguments);
  70. };
  71. }
  72.  
  73. // pack a function to a function that takes
  74. // it's arguments from a vector, one argument after
  75. // the other.
  76. template<std::size_t N, typename Arg, typename... Args, typename Fn>
  77. Function pack(Fn && fn)
  78. {
  79. return pack<N+1, Args...>([fn = std::forward<decltype(fn)>(fn)] (Arguments arguments, Args const &... args)
  80. {
  81. try
  82. {
  83. return fn(arguments, arguments.at(N), args...);
  84. }
  85. catch (std::bad_cast const &)
  86. {
  87. throw std::string{"argument "} + std::to_string(N) + std::string{" has wrong type "};
  88. }
  89. });
  90. }
  91.  
  92. // transform a function into one that takes its
  93. // arguments from a vector
  94. template<typename... Args, typename Fn>
  95. Function pack_function(Fn && fn)
  96. {
  97. return pack<0, Args...>([fn = std::forward<decltype(fn)>(fn)] (Arguments arguments, Args const &... args) -> bool
  98. {
  99. return fn(args...);
  100. });
  101. }
  102.  
  103. int main() {
  104. // Pack all the functions
  105. std::map<std::string, Function> operations;
  106. operations["Comp1_Data1_Data1"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
  107. {
  108. return Comp1::compute(dynamic_pointer_cast<Data1>(i1), dynamic_pointer_cast<Data1>(i2));
  109. });
  110. operations["Comp1_Data2_Data2"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
  111. {
  112. return Comp1::compute(dynamic_pointer_cast<Data2>(i1), dynamic_pointer_cast<Data2>(i2));
  113. });
  114. operations["Comp1_Data1_Data2"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
  115. {
  116. return Comp1::compute(dynamic_pointer_cast<Data1>(i1), dynamic_pointer_cast<Data2>(i2));
  117. });
  118. operations["Comp2_Data1"] = pack_function<shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1)
  119. {
  120. return Comp2::compute(dynamic_pointer_cast<Data1>(i1));
  121. });
  122. operations["Comp2_Data2"] = pack_function<shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1)
  123. {
  124. return Comp2::compute(dynamic_pointer_cast<Data2>(i1));
  125. });
  126.  
  127. // Create the possible inputs
  128. vector<shared_ptr<GenericData>> data1_data1 { shared_ptr<Data1>(), shared_ptr<Data1>() };
  129. vector<shared_ptr<GenericData>> data2_data2 { shared_ptr<Data2>(), shared_ptr<Data2>() };
  130. vector<shared_ptr<GenericData>> data1_data2 { shared_ptr<Data1>(), shared_ptr<Data2>() };
  131. vector<shared_ptr<GenericData>> data1 { shared_ptr<Data1>() };
  132. vector<shared_ptr<GenericData>> data2 { shared_ptr<Data2>() };
  133.  
  134. // The calls !
  135. operations["Comp1_Data1_Data1"](data1_data1);
  136. operations["Comp1_Data2_Data2"](data2_data2);
  137. operations["Comp1_Data1_Data2"](data1_data2);
  138. operations["Comp2_Data1"](data1);
  139. operations["Comp2_Data2"](data2);
  140.  
  141. // Wrong arguments
  142. try
  143. {
  144. operations["Comp1_Data1_Data1"](data1);
  145. }
  146. catch (std::string const & e)
  147. {
  148. cout << e << endl;
  149. }
  150. try
  151. {
  152. operations["Comp2_Data1"](data1_data1);
  153. }
  154. catch (std::string const & e)
  155. {
  156. cout << e << endl;
  157. }
  158. return 0;
  159. }
Success #stdin #stdout 0s 3476KB
stdin
Standard input is empty
stdout
Comp1::compute(Data1 input1, Data1 input2)null
Comp1::compute(Data2 input1, Data2 input2)
Comp1::compute(Data1 input1, Data2 input2)
Comp2::compute(Data1 input1)
Comp2::compute(Data2 input1)
wrong number of arguments, expected 2 but got 1
wrong number of arguments, expected 1 but got 2