fork download
  1. #include <memory>
  2. #include <functional>
  3. #include <iostream>
  4.  
  5. //@@@TODO:
  6. //std::equal_to
  7. //return types
  8. //specialize switch_any for `const char(&)[N]`
  9.  
  10. template<class othercases>
  11. struct switch_case_type : othercases {
  12. typedef typename othercases::value_type value_type;
  13. typedef std::function<void()> func_type;
  14.  
  15. switch_case_type(value_type label, func_type function, othercases rest) :othercases(std::move(rest)), l(std::move(label)), f(std::move(function)) {}
  16. switch_case_type(switch_case_type&& rhs) :othercases(std::move(rhs)), l(std::move(rhs.l)), f(std::move(rhs.f)) {}
  17. ~switch_case_type() { if (this->s) {do_switch(*(this->s)); this->s = nullptr;} }
  18. void do_switch(const value_type& switch_value) const {if (switch_value == l) f(); else othercases::do_switch(switch_value);}
  19.  
  20. template<class U>
  21. auto case_(U&& label, func_type function) -> switch_case_type<decltype(std::declval<othercases>().case_(std::forward<U>(label),std::move(function)))>
  22. {return {std::move(l), std::move(f), othercases::case_(std::move(label),std::move(function))};}
  23. switch_case_type&& default_(func_type function) /*&&*/ {this->d = std::move(function); return std::move(*this);}
  24. private:
  25. value_type l;
  26. std::function<void()> f;
  27. };
  28.  
  29. template<class T>
  30. struct switch_any_type {
  31. typedef T value_type;
  32. typedef std::function<void()> func_type;
  33.  
  34. switch_any_type() :s(nullptr) {}
  35. explicit switch_any_type(const T& switch_value) :s(&switch_value) {}
  36. switch_any_type(switch_any_type&& rhs) :s(rhs.s),d(std::move(rhs.d)) {rhs.s = nullptr;}
  37. ~switch_any_type() {if (s) d();}
  38. void do_switch(const value_type&) const {d();}
  39.  
  40. //switch_any_type& default_(func_type function) & {this->d = std::move(function); return *this;}
  41. switch_any_type&& default_(func_type function) /*&&*/ {this->d = std::move(function); return std::move(*this);}
  42. switch_case_type<switch_any_type<T>> case_(value_type label, func_type function)
  43. {return {std::move(label), std::move(function), std::move(*this)};}
  44. protected:
  45. const T* s;
  46. std::function<void()> d;
  47. };
  48.  
  49.  
  50. template<class T>
  51. switch_any_type<T> switch_any(const T& switch_value)
  52. {return switch_any_type<T>(switch_value);}
  53.  
  54.  
  55. #include <string>
  56. #include <iostream>
  57. int main() {
  58. try {
  59. std::string name="MooingDuck";
  60.  
  61. switch_any(name)
  62. .case_("MooingDuck", [&]{std::cout << "AWESOME\n";})
  63. .case_("CatPlusPlus", [&]{std::cout << "CRANKY DRUNKARD\n";})
  64. ;
  65.  
  66. static auto myswitch0 = switch_any_type<std::string>()
  67. .case_("A", [&]{std::cout << "A\n";})
  68. .default_([&]{std::cout << "B\n";})
  69. ;
  70. myswitch0.do_switch("A");
  71. myswitch0.do_switch("B");
  72.  
  73. static auto myswitch1 = switch_any_type<std::string>()
  74. .case_("MooingDuck", [&]{std::cout << "AWESOME\n";})
  75. .case_("CatPlusPlus", [&]{std::cout << "CRANKY DRUNKARD\n";})
  76. .case_("MooingDuck", [&]{std::cout << "WTFBUG\n";})
  77. ;
  78. myswitch1.do_switch(name);
  79. myswitch1.do_switch("CatPlusPlus");
  80. myswitch1.do_switch("Xeo");
  81.  
  82.  
  83. } catch(std::bad_function_call& bfc) {
  84. std::cout << "invalid name!";
  85. }
  86. }
  87.  
Success #stdin #stdout 0s 2996KB
stdin
Standard input is empty
stdout
AWESOME
A
B
AWESOME
CRANKY DRUNKARD
invalid name!