fork download
  1. #include <iostream>
  2.  
  3. // custom struct to ensure functions are called in the correct order
  4. template<int N>
  5. struct Precedence : public Precedence<N - 1> {};
  6. template<>
  7. struct Precedence<0> {};
  8.  
  9. // The main printer that delegates function calls of other classes.
  10. // Its 'print' function accepts classes that have defined:
  11. // - void print_time(int mins, double secs)
  12. // - void print_time(double total_secs)
  13. // - void print_time(int mins)
  14. // or none of the above.
  15. class PrinterDelegator {
  16. public:
  17. // The Precedence variable ensures the function with the highest 'N' value
  18. // gets called. If the function with the current 'N' value is ill-formed,
  19. // the Precedence struct will cast to its next highest base class until
  20. // a properly formed function is available.
  21. template<typename T>
  22. void print(const T &printer) {
  23. print(printer, p_);
  24. }
  25.  
  26. private:
  27. // these would all actually be incrementing
  28. int mins_{3};
  29. double secs_{22.5};
  30. double total_secs_{202.5};
  31.  
  32. Precedence<3> p_{};
  33.  
  34. // The "best" function. Call this if available
  35. template<typename T>
  36. auto print(const T &printer, const Precedence<3>&) -> decltype(printer.print_time(mins_, secs_)) {
  37. printer.print_time(mins_, secs_);
  38. }
  39. // Other available functions ordered by importance
  40. template<typename T>
  41. auto print(const T &printer, const Precedence<2>&) -> decltype(printer.print_time(total_secs_)) {
  42. printer.print_time(total_secs_);
  43. }
  44. template<typename T>
  45. auto print(const T &printer, const Precedence<1>&) -> decltype(printer.print_time(mins_)) {
  46. printer.print_time(mins_);
  47. }
  48. // default empty definition allowing for classes that haven't defined 'print_time'
  49. template<typename T>
  50. auto print(const T &printer, const Precedence<0>&) -> decltype(void()) {
  51. std::cout << "nothing" << std::endl;
  52. }
  53. };
  54.  
  55. // class with all possible functions. Only the "best"
  56. // one will get called: 'void print_time(int, double)'
  57. class VerbosePrinter {
  58. public:
  59. void print_time(int mins, double secs) const {
  60. print_time(mins);
  61. print_time(secs);
  62. }
  63. void print_time(double total_secs) const {
  64. std::cout << total_secs << "s" << std::endl;
  65. }
  66. void print_time(int mins) const {
  67. std::cout << mins << "m" << std::endl;
  68. }
  69. };
  70.  
  71. // Class with two of the function options. The best one here is
  72. // 'void print_time(double)' so that one will be called
  73. class SinglePrinter {
  74. public:
  75. void print_time(double total_secs) const {
  76. std::cout << total_secs << "s" << std::endl;
  77. }
  78. void print_time(int mins) const {
  79. std::cout << mins << "m" << std::endl;
  80. }
  81. };
  82.  
  83. // Empty class that can still be used even though no functions are defined
  84. class EmptyPrinter {};
  85.  
  86.  
  87. int main() {
  88. PrinterDelegator pd;
  89.  
  90. VerbosePrinter vp;
  91. std::cout << "Should print minutes and seconds:" << std::endl;
  92. pd.print(vp);
  93.  
  94. SinglePrinter sp;
  95. std::cout << "Should print total seconds:" << std::endl;
  96. pd.print(sp);
  97.  
  98. EmptyPrinter ep;
  99. std::cout << "Should print nothing:" << std::endl;
  100. pd.print(ep);
  101.  
  102. return 0;
  103. }
Success #stdin #stdout 0s 15240KB
stdin
Standard input is empty
stdout
Should print minutes and seconds:
3m
22.5s
Should print total seconds:
202.5s
Should print nothing:
nothing