fork(1) download
  1. #include <iostream> // For std::cout, std::boolalpha, std::endl.
  2. #include <string>
  3. #include <cstdint> // For int16_t.
  4. #include <type_traits> // For is_void<T>.
  5.  
  6. using FilePath = std::string;
  7.  
  8. // ---------------------
  9. // ExecuteMethod() functor:
  10. // ---------------------
  11.  
  12. // Default functor.
  13. template<typename... Ts>
  14. struct Executor { };
  15.  
  16. // General case.
  17. template<typename M, typename ReturnType, typename... Params>
  18. struct Executor<M, ReturnType (*)(Params...)> {
  19. public:
  20. // Parameter match:
  21. bool operator()(M method, Params... params) {
  22. ReturnType r = method(params...);
  23. std::cout << "Valid call. Return value: " << r << "." << std::endl;
  24. return true;
  25. }
  26.  
  27. // Parameter mismatch:
  28. template<typename... Invalid_Params>
  29. bool operator()(M method, Invalid_Params... ts) {
  30. std::cout << "Invalid call." << std::endl;
  31. return false;
  32. }
  33. };
  34.  
  35. // Special case to catch void return type.
  36. template<typename M, typename... Params>
  37. struct Executor<M, void (*)(Params...)> {
  38. public:
  39. // Parameter match:
  40. bool operator()(M method, Params... params) {
  41. method(params...);
  42. std::cout << "Valid call. Return value: None, 'cuz it's void." << std::endl;
  43. return true;
  44. }
  45.  
  46. // Parameter mismatch:
  47. template<typename... Invalid_Params>
  48. bool operator()(M method, Invalid_Params... ts) {
  49. std::cout << "Invalid call." << std::endl;
  50. return false;
  51. }
  52. };
  53.  
  54. #define ExecuteMethod(C, M, ...) \
  55.   do { \
  56.   Executor<decltype(&M), decltype(&M)> temp; \
  57.   C = temp(M, ##__VA_ARGS__); \
  58.   } while (false)
  59.  
  60.  
  61. // ---------------------
  62. // Example functions:
  63. // ---------------------
  64.  
  65. int GetColor(int16_t* color) { *color = 0xF249; return 42; }
  66. int GetFile(FilePath& file) { std::cout << "You want " << file << "? You can't handle the file!" << std::endl; return 24; }
  67. int WriteDocument(const FilePath &file, const char *fileFormatName, bool askForParms) { std::cout << "Do it yerself!" << std::endl; return 195; }
  68.  
  69. // Returns gibberish, to lighten everyone's day.
  70. int f0(int a) { std::cout << "You passed " << a << std::endl; }
  71.  
  72. bool f1(int& a, const float b) {
  73. std::cout << ((b > a) ? "b's bigger." : "a's bigger.") << std::endl;
  74. return (a > b);
  75. }
  76. float f2(float* a, const float* b) { return ++(*a) * (*b); }
  77.  
  78. char f3() { return 'c'; }
  79.  
  80. void f4(std::string& s) { s = "A different string."; }
  81.  
  82. // ---------------------
  83. // main():
  84. // ---------------------
  85.  
  86. int main() {
  87. int a = 8;
  88. float b1 = 2.0, b2 = 3.14;
  89. bool c = false;
  90. std::int16_t i16 = 0b1100010100001111; // Suddenly, binary literal!
  91. std::string s = "A string.";
  92. FilePath fp = "C:\\Windows\\system32\\chkntfs.exe";
  93.  
  94. std::cout << "Testing:" << std::endl;
  95. std::cout << "- - -" << std::endl;
  96. std::cout << std::boolalpha;
  97.  
  98. std::cout << "(int(*)(int), int):" << std::endl;
  99. ExecuteMethod(c, f0, a);
  100. std::cout << "c: " << c << std::endl << std::endl;
  101.  
  102. std::cout << "(int(*)(int), int, float):" << std::endl;
  103. ExecuteMethod(c, f0, a, b1);
  104. std::cout << "c: " << c << std::endl << std::endl;
  105.  
  106. std::cout << "(bool(*)(int&, const float), int&, const float):" << std::endl;
  107. ExecuteMethod(c, f1, a, b1);
  108. std::cout << "c: " << c << std::endl << std::endl;
  109.  
  110. std::cout << "(float(*)(float*, const float*):" << std::endl;
  111. ExecuteMethod(c, f2, &b1, &b2);
  112. std::cout << "Well, then. Once again, with const-ness!" << std::endl;
  113. std::cout << "Old values: " << b1 << ", " << b2 << std::endl;
  114. ExecuteMethod(c, f2, &b1, const_cast<const float*>(&b2));
  115. std::cout << "New values: " << b1 << ", " << b2 << std::endl;
  116. std::cout << "c: " << c << std::endl << std::endl;
  117.  
  118. std::cout << "(char(*)()):" << std::endl;
  119. ExecuteMethod(c, f3);
  120. std::cout << "c: " << c << std::endl << std::endl;
  121.  
  122. std::cout << "Reference testing:" << std::endl;
  123. std::cout << "(void(*)(std::string&), std::string&):" << std::endl;
  124. std::cout << "Original string: \"" << s << "\"" << std::endl;
  125. ExecuteMethod(c, f4, s);
  126. std::cout << "New string: \"" << s << "\"" << std::endl;
  127. std::cout << "c: " << c << std::endl << std::endl;
  128. std::cout << std::endl;
  129.  
  130. std::cout << "Now, let's try your example functions:" << std::endl;
  131. std::cout << "- - -" << std::endl;
  132. std::cout << "int GetColor(int16_t*):" << std::endl;
  133. std::cout << "Old value: " << i16 << std::endl;
  134. ExecuteMethod(c, GetColor, &i16);
  135. std::cout << "New value: " << i16 << std::endl;
  136. std::cout << "c: " << c << std::endl << std::endl;
  137.  
  138. std::cout << "int GetFile(FilePath&):" << std::endl;
  139. ExecuteMethod(c, GetFile, fp);
  140. std::cout << "c: " << c << std::endl << std::endl;
  141.  
  142. std::cout << "int WriteDocument(const FilePath&, const char*, bool):" << std::endl;
  143. ExecuteMethod(c, WriteDocument, fp, s.c_str(), true);
  144. std::cout << "c: " << c << std::endl << std::endl;
  145.  
  146. }
Success #stdin #stdout 0s 3464KB
stdin
Standard input is empty
stdout
Testing:
- - -
(int(*)(int), int):
You passed 8
Valid call.  Return value: 134525760.
c: true

(int(*)(int), int, float):
Invalid call.
c: false

(bool(*)(int&, const float), int&, const float):
a's bigger.
Valid call.  Return value: true.
c: true

(float(*)(float*, const float*):
Invalid call.
Well, then.  Once again, with const-ness!
Old values: 2, 3.14
Valid call.  Return value: 9.42.
New values: 3, 3.14
c: true

(char(*)()):
Valid call.  Return value: c.
c: true

Reference testing:
(void(*)(std::string&), std::string&):
Original string: "A string."
Valid call.  Return value: None, 'cuz it's void.
New string: "A different string."
c: true


Now, let's try your example functions:
- - -
int GetColor(int16_t*):
Old value: -15089
Valid call.  Return value: 42.
New value: -3511
c: true

int GetFile(FilePath&):
You want C:\Windows\system32\chkntfs.exe?  You can't handle the file!
Valid call.  Return value: 24.
c: true

int WriteDocument(const FilePath&, const char*, bool):
Do it yerself!
Valid call.  Return value: 195.
c: true